Commit for 2021.02.07.7z

This commit is contained in:
mrq 2021-02-07 00:00:00 -06:00
parent 910039a877
commit 160c7ff198
38 changed files with 5260 additions and 2532 deletions

View File

@ -1,116 +1,19 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#define SAMPLES 16
#define POISSON_DISK 4
#define RAY_MARCH_FOG 0
#define UF_DEFERRED_SAMPLING 1
#define UF_DEFERRED_SAMPLING 0
layout (constant_id = 0) const uint TEXTURES = 256;
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
int type;
int mapIndex;
float depthBias;
float padding;
mat4 view;
mat4 projection;
};
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int padding1;
int padding2;
int padding3;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
int textureIndex;
uint textures;
};
layout (input_attachment_index = 0, binding = 1) uniform usubpassInput samplerId;
layout (input_attachment_index = 1, binding = 2) uniform subpassInput samplerNormal;
#if UF_DEFERRED_SAMPLING
layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerUv;
#else
layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerAlbedo;
#endif
layout (input_attachment_index = 3, binding = 4) uniform subpassInput samplerDepth;
layout (binding = 5) uniform sampler3D samplerNoise;
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 7) readonly buffer Lights {
Light lights[];
};
layout (std140, binding = 8) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 9) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 10) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
struct Matrices {
mat4 view[2];
mat4 projection[2];
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
};
struct Space {
@ -142,7 +45,72 @@ struct Mode {
vec4 parameters;
};
layout (binding = 0) uniform UBO {
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
int type;
int mapIndex;
float depthBias;
float padding;
mat4 view;
mat4 projection;
};
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int modeAlpha;
int padding1;
int padding2;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
int textureIndex;
uint textures;
};
layout (input_attachment_index = 0, binding = 0) uniform usubpassInputMS samplerId;
layout (input_attachment_index = 1, binding = 1) uniform subpassInputMS samplerNormal;
#if UF_DEFERRED_SAMPLING
layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerUv;
#else
layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerAlbedo;
#endif
layout (input_attachment_index = 3, binding = 3) uniform subpassInputMS samplerDepth;
layout (binding = 4) uniform sampler3D samplerNoise;
layout (binding = 5) uniform samplerCube samplerSkybox;
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 7) uniform UBO {
Matrices matrices;
Mode mode;
@ -157,6 +125,44 @@ layout (binding = 0) uniform UBO {
float kexp;
} ubo;
layout (std140, binding = 8) readonly buffer Lights {
Light lights[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
vec3 Ls = vec3(1.0, 1.0, 1.0); // light specular
vec3 Ld = light.color; // light color
@ -476,9 +482,9 @@ void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightP
i += (kD * albedo / PI + specular) * radiance * NdotL;
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir ) {
vec3 t0 = (boundsMin - rayOrigin) / rayDir;
vec3 t1 = (boundsMax - rayOrigin) / rayDir;
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayO, vec3 rayD ) {
vec3 t0 = (boundsMin - rayO) / rayD;
vec3 t1 = (boundsMax - rayO) / rayD;
vec3 tmin = min(t0, t1);
vec3 tmax = max(t0, t1);
float dstA = max( max(tmin.x, tmin.y), tmin.z );
@ -493,26 +499,17 @@ float sampleDensity( vec3 position ) {
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
}
void fog( inout vec3 i, float scale ) {
void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
if ( ubo.fog.stepScale <= 0 ) return;
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
#if RAY_MARCH_FOG
mat4 iProjView = inverse( ubo.matrices.projection[inPushConstantPass] * ubo.matrices.view[inPushConstantPass] );
vec4 near4 = iProjView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = iProjView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
vec3 rayOrigin = near3;
vec3 rayDir = normalize( far3 - near3 );
float range = ubo.fog.range.y;
vec3 boundsMin = vec3(-range,-range,-range) + rayOrigin;
vec3 boundsMax = vec3(range,range,range) + rayOrigin;
vec3 boundsMin = vec3(-range,-range,-range) + rayO;
vec3 boundsMax = vec3(range,range,range) + rayO;
int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayOrigin, rayDir );
vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayO, rayD );
float dstToBox = rayBoxInfo.x;
float dstInsideBox = rayBoxInfo.y;
float depth = position.eye.z;
@ -526,7 +523,7 @@ void fog( inout vec3 i, float scale ) {
float totalDensity = 0;
float transmittance = 1;
while ( dstTravelled < dstLimit ) {
vec3 rayPos = rayOrigin + rayDir * (dstToBox + dstTravelled);
vec3 rayPos = rayO + rayD * (dstToBox + dstTravelled);
float density = sampleDensity(rayPos);
if ( density > 0 ) {
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
@ -557,49 +554,93 @@ vec3 decodeNormals( vec2 enc ) {
n.z = 1-f/2;
return normalize(n);
}
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < ubo.textures;
}
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
if ( !validTextureIndex( textureIndex ) ) return base;
vec4 sampleTexture( uint drawId, int textureIndex, in vec2 uv, vec4 base ) {
if ( !validTextureIndex( textureIndex ) ) return base;
Texture t = textures[textureIndex+1];
// if ( t.remap != textureIndex && validTextureIndex(t.remap) ) t = textures[t.remap+1];
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
float mip = mipLevel( uv );
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, wrap( uv ) ), mip );
}
void main() {
vec3 rayO = vec3(0);
vec3 rayD = vec3(0);
vec3 fragColor = vec3(0);
{
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
float depth = subpassLoad(samplerDepth).r;
float depth = subpassLoad(samplerDepth, SAMPLES).r;
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
vec4 positionEye = iProj * positionClip;
vec4 positionEye = ubo.matrices.iProjection[inPushConstantPass] * positionClip;
positionEye /= positionEye.w;
position.eye = positionEye.xyz;
vec4 positionWorld = iView * positionEye;
vec4 positionWorld = ubo.matrices.iView[inPushConstantPass] * positionEye;
position.world = positionWorld.xyz;
}
normal.eye = decodeNormals( subpassLoad(samplerNormal).xy );
{
vec4 near4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
uvec2 ID = subpassLoad(samplerId).xy;
rayO = near3;
}
{
mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
rayD = normalize( far3 - near3 );
}
normal.eye = decodeNormals( subpassLoad(samplerNormal, SAMPLES).xy );
uvec2 ID = subpassLoad(samplerId, SAMPLES).xy;
uint drawId = ID.x;
uint materialId = ID.y;
if ( drawId == 0 || materialId == 0 ) {
fragColor.rgb = texture( samplerSkybox, rayD ).rgb;
fog(rayO, rayD, fragColor, 0.0);
outFragColor = vec4(fragColor,1);
return;
}
--drawId;
--materialId;
DrawCall drawCall = drawCalls[drawId];
uint materialId = ID.y;
materialId += drawCall.materialIndex;
Material material = materials[materialId];
vec4 C = material.colorBase;
#if UF_DEFERRED_SAMPLING
vec2 uv = subpassLoad(samplerUv).xy;
vec2 uv = subpassLoad(samplerUv, SAMPLES).xy;
C = sampleTexture( drawId, drawCall.textureIndex + material.indexAlbedo, uv, C );
// OPAQUE
if ( material.modeAlpha == 0 ) C.a = 1;
// BLEND
else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
#else
C = subpassLoad(samplerAlbedo);
C = subpassLoad(samplerAlbedo, SAMPLES);
#endif
float M = material.factorMetallic;
@ -609,7 +650,7 @@ void main() {
bool usePbr = true;
bool gammaCorrect = false;
float litFactor = 1.0;
vec3 fragColor = C.rgb * ubo.ambient.rgb * AO;
fragColor = C.rgb * ubo.ambient.rgb * AO;
for ( uint i = 0; i < ubo.lights; ++i ) {
Light light = lights[i];
@ -636,7 +677,7 @@ void main() {
fragColor = pow(fragColor, vec3(1.0/2.2));
}
fog(fragColor, litFactor);
fog(rayO, rayD, fragColor, litFactor);
/*
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {

View File

@ -1,6 +1,6 @@
#version 450
#define UF_DEFERRED_SAMPLING 1
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (constant_id = 0) const uint TEXTURES = 1;
@ -21,10 +21,9 @@ struct Material {
int indexOcclusion;
int indexMetallicRoughness;
int modeAlpha;
int padding1;
int padding2;
int padding3;
};
struct Texture {
int index;
@ -62,43 +61,46 @@ vec2 encodeNormals( vec3 n ) {
return n.xy/p + 0.5;
}
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < TEXTURES;
}
vec4 sampleTexture( int textureIndex, vec2 uv, vec4 base ) {
if ( !validTextureIndex( textureIndex ) ) return base;
Texture t = textures[textureIndex+1];
// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1];
return texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
}
void main() {
float mip = mipLevel(inUv.xy);
vec2 uv = wrap(inUv.xy);
vec4 C = vec4(0, 0, 0, 0);
vec3 P = inPosition;
vec3 N = inNormal;
#if UF_DEFERRED_SAMPLING
outUvs = fract(inUv);
outUvs = wrap(inUv.xy);
vec4 outAlbedo = vec4(0,0,0,0);
#endif
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
int materialId = int(inId.y);
Material material = materials[materialId];
vec2 uv = fract(inUv.xy);
float M = material.factorMetallic;
float R = material.factorRoughness;
float AO = material.factorOcclusion;
// sample albedo
// C = sampleTexture( material.indexAlbedo, uv, material.colorBase );
if ( !validTextureIndex( material.indexAlbedo ) ) {
discard;
}
{
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
Texture t = textures[material.indexAlbedo + 1];
C = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
if ( C.a < abs(material.factorAlphaCutoff) ) discard;
C = textureLod( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
// alpha mode MASK
if ( material.modeAlpha == 0 ) C.a = 1;
else if ( material.modeAlpha == 2 && C.a < abs(material.factorAlphaCutoff) ) discard;
// alpha mode OPAQUE
}
#endif
@ -106,14 +108,14 @@ void main() {
// sample normal
if ( validTextureIndex( material.indexNormal ) ) {
Texture t = textures[material.indexNormal + 1];
N = inTBN * normalize( texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).xyz * 2.0 - vec3(1.0));
N = inTBN * normalize( textureLod( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip ).xyz * 2.0 - vec3(1.0));
}
#if 0
// sample metallic/roughness
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
Texture t = textures[material.indexMetallicRoughness + 1];
vec4 sampled = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
vec4 sampled = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
M = sampled.b;
R = sampled.g;
}
@ -124,84 +126,9 @@ void main() {
AO = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).r;
}
#endif
C.rgb *= inColor.rgb * C.a;
outAlbedo = vec4(C.rgb,1);
outAlbedo = C * inColor;
#endif
outNormals = encodeNormals( N );
outId = ivec2(inId.w, inId.y);
}
/*
layout (location = 0) out vec4 outAlbedoMetallic;
layout (location = 1) out vec4 outNormalRoughness;
layout (location = 2) out vec4 outPositionAO;
bool validIndex( int index ) {
return 0 <= index && index < TEXTURES;
}
vec4 sampleTexture( int index ) {
return texture(samplerTextures[index], inUv.xy);
}
void main() {
int materialId = int(inId.y);
vec4 C = vec4(1, 0, 1, 1);
vec3 N = inNormal;
vec3 P = inPosition;
float M = 1;
float R = 1;
float AO = 1;
if ( 0 <= materialId && materialId < materials.length() ) {
Material material = materials[materialId];
// sample albedo
C = material.colorBase;
if ( validIndex( material.indexAlbedo ) ) {
C = sampleTexture( material.indexAlbedo );
if ( material.indexAlbedo != material.indexMappedTarget && validIndex( material.indexMappedTarget ) ) {
C = mix( C, sampleTexture( material.indexMappedTarget ), material.factorMappedBlend );
}
} else if ( validIndex( material.indexMappedTarget ) ) {
C = sampleTexture( material.indexMappedTarget );
}
// debug
if ( material.factorAlphaCutoff < 0 ) {
float percent = float(material.indexAlbedo) / float(TEXTURES);
if ( percent < 0.33 ) {
C.rgb = vec3( percent * 3, 0, 0 );
} else if ( percent < 0.66 ) {
C.rgb = vec3( 0, percent * 3, 0 );
} else {
C.rgb = vec3( 0, 0, percent * 3 );
}
}
if ( C.a < abs(material.factorAlphaCutoff) ) discard;
// sample normal
if ( validIndex( material.indexNormal ) ) {
N = inTBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - vec3(1.0));
}
// sample metallic/roughness
M = material.factorMetallic;
R = material.factorRoughness;
if ( validIndex( material.indexMetallicRoughness ) ) {
vec4 sampled = sampleTexture( material.indexMetallicRoughness );
M = sampled.b;
R = sampled.g;
}
AO = material.factorOcclusion;
if ( validIndex( material.indexOcclusion ) ) {
AO = sampleTexture( material.indexOcclusion ).r;
}
}
C.rgb *= inColor.rgb * C.a;
outAlbedoMetallic = vec4(C.rgb,M);
outNormalRoughness = vec4(N,R);
outPositionAO = vec4(P,AO);
}
*/
outId = ivec2(inId.w+1, inId.y+1);
}

View File

@ -5,7 +5,7 @@
#include <uf/utils/mempool/mempool.h>
#define HANDLE_EXCEPTIONS 0
#define HANDLE_EXCEPTIONS 1
int main(int argc, char** argv){
for ( size_t i = 0; i < argc; ++i ) {

View File

@ -48,6 +48,7 @@ namespace uf {
uf::Entity* UF_API alloc( size_t );
template<typename T> T* alloc();
void UF_API free( uf::Entity* );
bool UF_API valid( uf::Entity* );
uf::Entity* UF_API reuse( size_t );
size_t UF_API collect( uint8_t = 0 );

View File

@ -14,10 +14,17 @@
namespace pod {
struct UF_API DrawCall {
alignas(4) int32_t materialIndex = -1;
alignas(4) uint32_t materials = 0;
alignas(4) int32_t textureIndex = -1;
alignas(4) uint32_t textures = 0;
std::string name = "";
struct Storage {
alignas(4) int32_t materialIndex = -1;
alignas(4) uint32_t materials = 0;
alignas(4) int32_t textureIndex = -1;
alignas(4) uint32_t textures = 0;
} storage;
size_t verticesIndex = 0;
size_t vertices = 0;
size_t indicesIndex = 0;
size_t indices = 0;
};
struct UF_API Texture {
std::string name = "";
@ -58,6 +65,7 @@ namespace pod {
*/
struct UF_API Material {
std::string name = "";
std::string alphaMode = "";
//
struct Storage {
alignas(16) pod::Vector4f colorBase = { 0, 0, 0, 0 };
@ -68,15 +76,15 @@ namespace pod {
alignas(4) float factorOcclusion = 0.0f;
alignas(4) float factorAlphaCutoff = 1.0f;
alignas(4) int indexAlbedo = -1;
alignas(4) int indexNormal = -1;
alignas(4) int indexEmissive = -1;
alignas(4) int indexOcclusion = -1;
alignas(4) int32_t indexAlbedo = -1;
alignas(4) int32_t indexNormal = -1;
alignas(4) int32_t indexEmissive = -1;
alignas(4) int32_t indexOcclusion = -1;
alignas(4) int indexMetallicRoughness = -1;
alignas(4) int padding1 = -1;
alignas(4) int padding2 = -1;
alignas(4) int padding3 = -1;
alignas(4) int32_t indexMetallicRoughness = -1;
alignas(4) int32_t modeAlpha = -1;
alignas(4) int32_t padding1 = -1;
alignas(4) int32_t padding2 = -1;
} storage;
};
struct UF_API Node {
@ -84,22 +92,21 @@ namespace pod {
std::string name = "";
int32_t index = -1;
// Node* parent = NULL;
// std::vector<Node*> children;
int32_t parent = -1;
std::vector<int32_t> children;
uf::Object* entity = NULL;
size_t jointBufferIndex = -1;
size_t materialBufferIndex = -1;
size_t textureBufferIndex = -1;
int32_t jointBufferIndex = -1;
int32_t materialBufferIndex = -1;
int32_t textureBufferIndex = -1;
int32_t skin = -1;
Mesh mesh;
uf::Collider collider;
pod::Transform<> transform;
std::vector<pod::DrawCall> primitives;
pod::DrawCall drawCall;
};
struct UF_API Skin {
@ -146,6 +153,7 @@ namespace pod {
std::vector<pod::Texture> textures;
std::vector<pod::Material> materials;
std::vector<pod::Light> lights;
pod::DrawCall drawCall;
std::vector<Skin> skins;
std::unordered_map<std::string, Animation> animations;

View File

@ -37,13 +37,6 @@
#define VK_FLAGS_NONE 0
#define DEFAULT_FENCE_TIMEOUT 100000000000
namespace ext {
namespace vulkan {
std::string errorString( VkResult result );
void* alignedAlloc( size_t size, size_t alignment );
void alignedFree(void* data);
}
}
#define VK_DEFAULT_STAGE_BUFFERS 1
#include <vk_mem_alloc.h>

View File

@ -3,8 +3,6 @@
#include <uf/ext/vulkan.h>
#include <vector>
#define VK_DEFAULT_STAGE_BUFFERS 1
namespace ext {
namespace vulkan {
struct Device;
@ -68,9 +66,9 @@ namespace ext {
void initialize( Device& device );
void destroy();
//
size_t initializeBuffer( void* data, VkDeviceSize length, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, bool stage = VK_DEFAULT_STAGE_BUFFERS );
template<typename T> inline size_t initializeBuffer( T data, VkDeviceSize length, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (void*) &data, length, usageFlags, memoryPropertyFlags, stage ); }
template<typename T> inline size_t initializeBuffer( T data, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (void*) &data, static_cast<VkDeviceSize>(sizeof(T)), usageFlags, memoryPropertyFlags, stage ); }
size_t initializeBuffer( void* data, VkDeviceSize length, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool stage = VK_DEFAULT_STAGE_BUFFERS );
template<typename T> inline size_t initializeBuffer( T data, VkDeviceSize length, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (void*) &data, length, usageFlags, memoryPropertyFlags, stage ); }
template<typename T> inline size_t initializeBuffer( T data, VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (void*) &data, static_cast<VkDeviceSize>(sizeof(T)), usageFlags, memoryPropertyFlags, stage ); }
void updateBuffer( void* data, VkDeviceSize length, size_t index = 0, bool stage = VK_DEFAULT_STAGE_BUFFERS );
void updateBuffer( void* data, VkDeviceSize length, Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS );

View File

@ -73,6 +73,7 @@ namespace ext {
VkDescriptorSetLayout descriptorSetLayout;
VkDescriptorPool descriptorPool;
VkDescriptorSet descriptorSet;
GraphicDescriptor descriptor;
void initialize( Graphic& graphic );
void initialize( Graphic& graphic, GraphicDescriptor& descriptor );
@ -114,7 +115,7 @@ namespace ext {
void destroy();
template<typename T, typename U>
void initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t = SIZE_MAX, bool stage = VK_DEFAULT_STAGE_BUFFERS );
void initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t = SIZE_MAX );
bool hasPipeline( GraphicDescriptor& descriptor );
void initializePipeline();

View File

@ -1,5 +1,5 @@
template<typename T, typename U>
void ext::vulkan::Graphic::initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t o, bool stage ) {
void ext::vulkan::Graphic::initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t o ) {
if ( mesh.indices.empty() ) mesh.initialize( o );
mesh.updateDescriptor();
@ -9,19 +9,26 @@ void ext::vulkan::Graphic::initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t
// too lazy to check if this equals, only matters in pipeline creation anyways
descriptor.geometry = mesh;
updateBuffer(
(void*) mesh.vertices.data(),
mesh.vertices.size() * mesh.sizes.vertex,
0,
stage
);
updateBuffer(
(void*) mesh.indices.data(),
mesh.indices.size() * mesh.sizes.indices,
1,
stage
);
return;
int32_t vertexBuffer = -1;
int32_t indexBuffer = -1;
for ( size_t i = 0; i < buffers.size(); ++i ) {
if ( buffers[i].usageFlags & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ) vertexBuffer = i;
if ( buffers[i].usageFlags & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ) indexBuffer = i;
}
if ( vertexBuffer > 0 && indexBuffer > 0 ) {
updateBuffer(
(void*) mesh.vertices.data(),
mesh.vertices.size() * mesh.sizes.vertex,
vertexBuffer
);
updateBuffer(
(void*) mesh.indices.data(),
mesh.indices.size() * mesh.sizes.indices,
indexBuffer
);
return;
}
}
// can't reuse buffers, re-create buffers
{
@ -36,15 +43,11 @@ void ext::vulkan::Graphic::initializeGeometry( uf::BaseMesh<T, U>& mesh, size_t
initializeBuffer(
(void*) mesh.vertices.data(),
mesh.vertices.size() * mesh.sizes.vertex,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
stage
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
);
initializeBuffer(
(void*) mesh.indices.data(),
mesh.indices.size() * mesh.sizes.indices,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
stage
VK_BUFFER_USAGE_INDEX_BUFFER_BIT
);
}

View File

@ -5,12 +5,15 @@
namespace ext {
namespace vulkan {
struct UF_API RenderTarget {
typedef struct {
VkFormat format;
VkImageLayout layout;
VkImageUsageFlags usage;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
bool aliased = false;
struct Attachment {
struct Descriptor {
VkFormat format;
VkImageLayout layout;
VkImageUsageFlags usage;
bool blend = false;
uint8_t samples = 1;
bool aliased = false;
} descriptor;
VkImage image;
VkDeviceMemory mem;
@ -18,17 +21,18 @@ namespace ext {
VmaAllocation allocation;
VmaAllocationInfo allocationInfo;
VkPipelineColorBlendAttachmentState blendState;
} Attachment;
};
std::vector<Attachment> attachments;
typedef struct {
struct Subpass {
VkPipelineStageFlags stage;
VkAccessFlags access;
std::vector<VkAttachmentReference> colors;
std::vector<VkAttachmentReference> inputs;
std::vector<VkAttachmentReference> resolves;
VkAttachmentReference depth;
} Subpass;
};
std::vector<Subpass> passes;
bool initialized = false;
@ -37,13 +41,12 @@ namespace ext {
std::vector<VkFramebuffer> framebuffers;
uint32_t width = 0;
uint32_t height = 0;
uint8_t multiviews = 1;
uint8_t samples = 1;
uint8_t views = 1;
// RAII
void initialize( Device& device );
void destroy();
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, size_t );
size_t attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, bool blend = false, Attachment* attachment = NULL );
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, const std::vector<size_t>&, size_t );
size_t attach( const Attachment::Descriptor& descriptor, Attachment* attachment = NULL );
};
}
}

View File

@ -44,6 +44,8 @@ namespace ext {
VkImage image;
VkImageView view;
VkImageType type;
VkImageViewType viewType;
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkDeviceMemory deviceMemory;
VkDescriptorImageInfo descriptor;
@ -55,9 +57,10 @@ namespace ext {
VmaAllocationInfo allocationInfo;
uint32_t width, height, depth, layers;
uint32_t mips;
uint32_t mips = 1;
// RAII
void initialize( Device& device, size_t width, size_t height, size_t depth = 1, size_t layers = 1 );
void initialize( Device& device, VkImageViewType, size_t width, size_t height, size_t depth = 1, size_t layers = 1 );
void updateDescriptors();
void destroy();
bool generated() const;
@ -76,9 +79,6 @@ namespace ext {
VkImageLayout newImageLayout,
uint32_t mipLevels
);
};
struct UF_API Texture2D : public Texture {
static Texture2D empty;
void loadFromFile(
std::string filename,
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
@ -118,10 +118,12 @@ namespace ext {
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
);
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM );
void aliasTexture( const Texture2D& );
void aliasTexture( const Texture& );
void aliasAttachment( const RenderTarget::Attachment& attachment, bool = true );
void update( uf::Image& image, VkImageLayout, uint32_t layer = 1 );
void update( void*, VkDeviceSize, VkImageLayout, uint32_t layer = 1 );
inline void fromBuffers(
void* buffer,
VkDeviceSize bufferSize,
@ -137,5 +139,18 @@ namespace ext {
void generateMipmaps(VkCommandBuffer commandBuffer, uint32_t layer = 1);
};
class UF_API Texture2D : public Texture {
public:
Texture2D();
static Texture2D empty;
};
class UF_API Texture3D : public Texture {
public:
Texture3D();
};
class UF_API TextureCube : public Texture {
public:
TextureCube();
};
}
}

View File

@ -28,7 +28,11 @@ namespace ext {
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData
);
uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties);
std::string errorString( VkResult result );
VkSampleCountFlagBits sampleCount( uint8_t );
void* alignedAlloc( size_t size, size_t alignment );
void alignedFree(void* data);
typedef VmaAllocator Allocator;

View File

@ -14,3 +14,6 @@
};\
double time = 0;\
if ( __VA_ARGS__ (time = TOKEN_PASTE(TIMER, __LINE__)(x)) >= x )
#define UF_DEBUG 1
#define UF_DEBUG_PRINT() if ( UF_DEBUG ) uf::iostream << __FILE__ << ":" << __FUNCTION__ << "@" << __LINE__ << "\n";

View File

@ -37,11 +37,17 @@ namespace ext {
uf::BaseGeometry geometry;
size_t indices = 0;
struct {
size_t vertex = 0;
size_t index = 0;
} offsets;
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkPolygonMode fill = VK_POLYGON_MODE_FILL;
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
float lineWidth = 1.0f;
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
struct {
VkBool32 test = true;
VkBool32 write = true;

View File

@ -27,7 +27,7 @@ namespace uf {
Image( Image::container_t&& move, const Image::vec2_t& size ); // Move from vector of pixels
Image( const Image::container_t& copy, const Image::vec2_t& size ); // Copy from vector of pixels
bool open( const std::string& filename ); // from file
bool open( const std::string& filename, bool = true ); // from file
void open( const std::istream& stream ); // from stream
void move( Image::container_t&& move, const Image::vec2_t& size ); // move from vector of pixels
void copy( const Image::container_t& copy, const Image::vec2_t& size ); // copy from vector of pixels

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,20 @@
#include <uf/engine/entity/entity.h>
#include <uf/engine/instantiator/instantiator.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Entity)
uf::Entity::Entity() UF_BEHAVIOR_ENTITY_CPP_ATTACH(uf::Entity)
#define this ((uf::Entity*) &self)
void uf::EntityBehavior::initialize( uf::Object& self ) {
if ( !this->isValid() )
this->m_uid = ++uf::Entity::uids;
if ( !this->isValid() ) this->m_uid = ++uf::Entity::uids;
// sanitize children
/*
for ( auto& kv : this->m_children ) {
if ( !uf::instantiator::valid(kv) ) {
std::cout << "FOUND INVALID CHILD IN " << this->getName() << ": " << this->getUid() << ": " << kv << std::endl;
kv = NULL;
}
}
*/
}
void uf::EntityBehavior::tick( uf::Object& self ) {
for ( uf::Entity* kv : this->m_children ) {

View File

@ -79,6 +79,19 @@ void uf::instantiator::free( uf::Entity* pointer ) {
else ::free( pointer );
#endif
}
bool uf::instantiator::valid( uf::Entity* pointer ) {
#if UF_MEMORYPOOL_INVALID_FREE
uf::MemoryPool& memoryPool = uf::Entity::memoryPool.size() > 0 ? uf::Entity::memoryPool : uf::MemoryPool::global;
return memoryPool.exists( pointer );
#else
uf::MemoryPool* memoryPool = NULL;
if ( uf::Entity::memoryPool.size() > 0 )
memoryPool = &uf::Entity::memoryPool;
else if ( uf::MemoryPool::global.size() > 0 )
memoryPool = &uf::MemoryPool::global;
return memoryPool ? memoryPool->exists( pointer ) : pointer && pointer->isValid();
#endif
}
void uf::instantiator::registerBinding( const std::string& object, const std::string& behavior ) {
if ( !objects ) objects = new pod::NamedTypes<pod::Instantiator>;

View File

@ -71,7 +71,7 @@ void uf::scene::unloadScene() {
uf::Scene* current = uf::scene::scenes.back();
current->destroy();
uf::scene::scenes.pop_back();
delete current;
//delete current;
}
uf::Scene& uf::scene::getCurrentScene() {
return *uf::scene::scenes.back();

View File

@ -105,11 +105,17 @@ namespace {
auto& mesh = graph.nodes[nodeIndex].mesh;
auto& collider = graph.nodes[nodeIndex].collider;
if ( node.mesh > -1 ) {
auto& drawCall = graph.nodes[nodeIndex].drawCall;
drawCall.name = node.name;
drawCall.verticesIndex = mesh.vertices.size();
drawCall.indicesIndex = mesh.indices.size();
drawCall.vertices = 0;
drawCall.indices = 0;
for ( auto& primitive : model.meshes[node.mesh].primitives ) {
size_t verticesStart = mesh.vertices.size();
size_t indicesStart = mesh.indices.size();
auto& dc = graph.nodes[nodeIndex].primitives.emplace_back();
dc.verticesIndex = mesh.vertices.size();
dc.indicesIndex = mesh.indices.size();
size_t vertices = 0;
struct Attribute {
std::string name = "";
size_t components = 1;
@ -135,7 +141,7 @@ namespace {
auto& view = model.bufferViews[accessor.bufferView];
if ( attribute.name == "POSITION" ) {
vertices = accessor.count;
dc.vertices = accessor.count;
pod::Vector3f minCorner = { accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
pod::Vector3f maxCorner = { accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
@ -158,8 +164,8 @@ namespace {
}
auto modelMatrix = uf::transform::model( transform );
mesh.vertices.reserve( vertices + verticesStart );
for ( size_t i = 0; i < vertices; ++i ) {
mesh.vertices.reserve( dc.vertices + dc.verticesIndex );
for ( size_t i = 0; i < dc.vertices; ++i ) {
#define ITERATE_ATTRIBUTE( name, member )\
if ( !attributes[name].indices.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
@ -205,13 +211,13 @@ namespace {
auto& view = model.bufferViews[accessor.bufferView];
auto& buffer = model.buffers[view.buffer];
auto indices = static_cast<uint32_t>(accessor.count);
mesh.indices.reserve( indices + indicesStart );
dc.indices = static_cast<uint32_t>(accessor.count);
mesh.indices.reserve( dc.indices + dc.indicesIndex );
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
#define COPY_INDICES()\
for (size_t index = 0; index < indices; index++)\
mesh.indices.emplace_back(buf[index] + verticesStart);
for (size_t index = 0; index < dc.indices; index++)\
mesh.indices.emplace_back(buf[index] + dc.verticesIndex);
switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
@ -232,6 +238,12 @@ namespace {
}
#undef COPY_INDICES
}
drawCall.vertices += dc.vertices;
drawCall.indices += dc.indices;
graph.drawCall.vertices += dc.vertices;
graph.drawCall.indices += dc.indices;
/*
if ( graph.mode & ext::gltf::LoadMode::TRANSFORM ) {
auto model = uf::transform::model( transform );
@ -344,29 +356,18 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
material.storage.factorMetallic = m.pbrMetallicRoughness.metallicFactor;
material.storage.factorRoughness = m.pbrMetallicRoughness.roughnessFactor;
material.storage.factorOcclusion = m.occlusionTexture.strength;
/*
if ( 0 <= material.storage.indexAlbedo && material.storage.indexAlbedo < graph.textures.size() ) {
auto& texture = graph.textures[material.storage.indexAlbedo];
material.storage.indexAlbedo = texture.storage.index;
material.storage.factorAlphaCutoff = m.alphaCutoff;
material.alphaMode = m.alphaMode;
if ( material.alphaMode == "OPAQUE" ) {
material.storage.modeAlpha = 0;
} else if ( material.alphaMode == "BLEND" ) {
material.storage.modeAlpha = 1;
} else if ( material.alphaMode == "MASK" ) {
material.storage.modeAlpha = 2;
} else {
std::cout << "Unhandled alpha mode: " << material.alphaMode << std::endl;
}
if ( 0 <= material.storage.indexNormal && material.storage.indexNormal < graph.textures.size() ) {
auto& texture = graph.textures[material.storage.indexNormal];
material.storage.indexNormal = texture.storage.index;
}
if ( 0 <= material.storage.indexEmissive && material.storage.indexEmissive < graph.textures.size() ) {
auto& texture = graph.textures[material.storage.indexEmissive];
material.storage.indexEmissive = texture.storage.index;
}
if ( 0 <= material.storage.indexOcclusion && material.storage.indexOcclusion < graph.textures.size() ) {
auto& texture = graph.textures[material.storage.indexOcclusion];
material.storage.indexOcclusion = texture.storage.index;
}
if ( 0 <= material.storage.indexMetallicRoughness && material.storage.indexMetallicRoughness < graph.textures.size() ) {
auto& texture = graph.textures[material.storage.indexMetallicRoughness];
material.storage.indexMetallicRoughness = texture.storage.index;
}
*/
}
}
// load node information/meshes

View File

@ -178,8 +178,7 @@ void uf::graph::process( pod::Graph& graph ) {
graph.instanceBufferIndex = graphic.initializeBuffer(
(void*) instances.data(),
instances.size() * sizeof(pod::Matrix4f),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
// Joints storage buffer
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
@ -188,9 +187,8 @@ void uf::graph::process( pod::Graph& graph ) {
auto& skin = graph.skins[node.skin];
node.jointBufferIndex = graphic.initializeBuffer(
(void*) skin.inverseBindMatrices.data(),
skin.inverseBindMatrices.size() * sizeof(pod::Matrix4f),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
(1 + skin.inverseBindMatrices.size()) * sizeof(pod::Matrix4f),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
break;
}
@ -205,8 +203,7 @@ void uf::graph::process( pod::Graph& graph ) {
graph.root.materialBufferIndex = graphic.initializeBuffer(
(void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
// Texture storage buffer
std::vector<pod::Texture::Storage> textures( graph.textures.size() );
@ -217,8 +214,7 @@ void uf::graph::process( pod::Graph& graph ) {
graph.root.textureBufferIndex = graphic.initializeBuffer(
(void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
@ -328,7 +324,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
for ( auto& l : graph.lights ) {
if ( l.name != node.name ) continue;
entity.load("/light.json");
auto& metadata = entity.getComponent<uf::Serializer>();
auto& metadata = entity.getComponent<uf::Serializer>();
metadata["light"]["radius"][0] = 0.001;
metadata["light"]["radius"][1] = l.range; // l.range <= 0.001f ? graph.metadata["lights"]["range cap"].as<float>() : l.range;
metadata["light"]["power"] = l.intensity; // * graph.metadata["lights"]["power scale"].as<float>();
@ -350,6 +347,26 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( key == "transform" ) return;
metadata["light"][key] = value;
});
if ( metadata["light"]["shadows"].as<bool>() ) {
ext::json::Value m;
if ( ext::json::isObject( graph.metadata["tags"][node.name]["renderMode"] ) ) {
m = graph.metadata["tags"][node.name]["renderMode"];
} else if ( ext::json::isObject( graph.metadata["lights"]["renderMode"] ) ) {
m = graph.metadata["lights"]["renderMode"];
}
if ( m["target"].is<std::string>() ) {
std::string targetNode = m["target"].as<std::string>();
auto* node = uf::graph::find( graph, targetNode );
if ( node ) {
auto& drawCall = node->drawCall;
size_t targetIndices = graph.drawCall.indices;
metadata["renderMode"]["target"][std::to_string(targetIndices)]["size"] = drawCall.indices;
metadata["renderMode"]["target"][std::to_string(targetIndices)]["offset"] = drawCall.indicesIndex;
// std::cout << "Found " << targetNode << ", Replacing " << targetNode << " with " << drawCall.indicesIndex << " + " << drawCall.indices << std::endl;
}
}
}
// auto& transform = entity.getComponent<pod::Transform<>>();
// transform.orientation = uf::quaternion::inverse( transform.orientation );
break;
@ -423,9 +440,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
node.jointBufferIndex = graphic.initializeBuffer(
(void*) skin.inverseBindMatrices.data(),
skin.inverseBindMatrices.size() * sizeof(pod::Matrix4f),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
true
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
// Materials storage buffer
@ -433,18 +448,18 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
materials[i] = graph.materials[i].storage;
}
/*
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
auto& info = graph.metadata["tags"][node.name];
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
materials[i].factorAlphaCutoff = info["alpha cutoff"].as<float>();
}
}
*/
node.materialBufferIndex = graphic.initializeBuffer(
(void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
true
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
// Texture storage buffer
std::vector<pod::Texture::Storage> textures( graph.textures.size() );
@ -455,8 +470,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
graph.root.textureBufferIndex = graphic.initializeBuffer(
(void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
}
@ -598,5 +612,8 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) {
}
}
void uf::graph::destroy( pod::Graph& graph ) {
for ( auto& t : graph.textures ) {
t.texture.destroy();
}
delete graph.atlas;
}

View File

@ -426,12 +426,12 @@ bool ext::openvr::requestRenderModel( const std::string& name ) {
return false;
}
void ext::openvr::submit() { bool invert = swapEyes;
ext::vulkan::StereoscopicDeferredRenderMode* renderMode = (ext::vulkan::StereoscopicDeferredRenderMode*) &ext::vulkan::getRenderMode("");
auto& renderMode = ext::vulkan::getRenderMode("");
float width = renderMode->width > 0 ? renderMode->width : uf::renderer::settings::width;
float height = renderMode->height > 0 ? renderMode->height : uf::renderer::settings::height;
auto& leftOutputAttachment = renderMode->renderTargets.left.attachments[renderMode->renderTargets.left.attachments.size()-1];
auto& rightOutputAttachment = renderMode->renderTargets.right.attachments[renderMode->renderTargets.right.attachments.size()-1];
float width = renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width;
float height = renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height;
auto& leftOutputAttachment = renderMode.renderTarget.attachments[renderMode.metadata["outputs"][0].as<size_t>()];
auto& rightOutputAttachment = renderMode.renderTarget.attachments[renderMode.metadata["outputs"][1].as<size_t>()];
// Submit to SteamVR
vr::VRTextureBounds_t bounds;
@ -453,12 +453,12 @@ void ext::openvr::submit() { bool invert = swapEyes;
vr::Texture_t texture = { &vulkanData, vr::TextureType_Vulkan, vr::ColorSpace_Auto };
vulkanData.m_nFormat = leftOutputAttachment.format;
vulkanData.m_nFormat = leftOutputAttachment.descriptor.format;
vulkanData.m_nImage = (uint64_t) (VkImage) leftOutputAttachment.image;
// if ( DEBUG_MARKER ) std::cout << leftOutputAttachment.image << std::endl;
vr::VRCompositor()->Submit( invert ? vr::Eye_Right : vr::Eye_Left, &texture, &bounds );
vulkanData.m_nFormat = rightOutputAttachment.format;
vulkanData.m_nFormat = rightOutputAttachment.descriptor.format;
vulkanData.m_nImage = (uint64_t) (VkImage) rightOutputAttachment.image;
// if ( DEBUG_MARKER ) std::cout << rightOutputAttachment.image << std::endl;
vr::VRCompositor()->Submit( invert ? vr::Eye_Left : vr::Eye_Right, &texture, &bounds );

View File

@ -171,12 +171,12 @@ size_t ext::vulkan::Buffers::initializeBuffer( void* data, VkDeviceSize length,
length
));
this->updateBuffer( data, length, buffer, stage );
// size_t index = buffers.size();
// buffers.push_back( std::move(buffer) );
return index;
}
// VkQueue queue = device->queues.transfer;
// implicitly set properties
usageFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
Buffer staging;
VkDeviceSize storageBufferSize = length;
device->createBuffer(

View File

@ -250,7 +250,7 @@ uint32_t ext::vulkan::Device::getMemoryType( uint32_t typeBits, VkMemoryProperty
*memTypeFound = false;
return 0;
}
throw std::runtime_error("Could not find a matching memory type");
// throw std::runtime_error("Could not find a matching memory type");
}
int ext::vulkan::Device::rate( VkPhysicalDevice device ) {
@ -381,7 +381,6 @@ VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usageFlags, VkMem
// Attach the memory to the buffer object
VK_CHECK_RESULT(vkBindBufferMemory(logicalDevice, *buffer, *memory, 0));
return VK_SUCCESS;
}
@ -573,10 +572,10 @@ void ext::vulkan::Device::initialize() {
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Program";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.applicationVersion = VK_MAKE_VERSION(1, 2, 0);
appInfo.pEngineName = "Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
appInfo.engineVersion = VK_MAKE_VERSION(1, 2, 0);
appInfo.apiVersion = VK_API_VERSION_1_2;
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -908,6 +907,15 @@ void ext::vulkan::Device::initialize() {
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
VK_CHECK_RESULT(vkCreatePipelineCache( device, &pipelineCacheCreateInfo, nullptr, &this->pipelineCache));
}
// setup allocator
{
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.instance = instance;
allocatorInfo.device = logicalDevice;
vmaCreateAllocator(&allocatorInfo, &allocator);
}
}
void ext::vulkan::Device::destroy() {
@ -943,4 +951,5 @@ void ext::vulkan::Device::destroy() {
vkDestroyInstance( this->instance, nullptr );
this->instance = nullptr;
}
vmaDestroyAllocator( allocator );
}

View File

@ -644,9 +644,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
initializeBuffer(
(void*) userdata.data,
userdata.len,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
false
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
);
}
}
@ -778,6 +776,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
}
void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& descriptor ) {
this->device = graphic.device;
//this->descriptor = descriptor;
Device& device = *graphic.device;
// VK_VALIDATION_MESSAGE(&graphic << ": Shaders: " << graphic.material.shaders.size() << " Textures: " << graphic.material.textures.size());
@ -884,10 +883,13 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
if ( renderMode.getType() != "Swapchain" ) {
auto& subpass = renderTarget.passes[descriptor.subpass];
for ( auto& color : subpass.colors ) {
blendAttachmentStates.push_back(renderTarget.attachments[color.attachment].blendState);
auto& attachment = renderTarget.attachments[color.attachment];
blendAttachmentStates.push_back(attachment.blendState);
samples = std::max(samples, ext::vulkan::sampleCount( attachment.descriptor.samples ));
}
// require blending if independentBlend is not an enabled feature
if ( device.enabledFeatures.independentBlend == VK_FALSE ) {
@ -933,21 +935,16 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
VkPipelineViewportStateCreateInfo viewportState = ext::vulkan::initializers::pipelineViewportStateCreateInfo(
1, 1, 0
);
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
// switch ( ext::vulkan::settings::msaa ) {
switch ( renderTarget.samples ) {
case 64: samples = VK_SAMPLE_COUNT_64_BIT; break;
case 32: samples = VK_SAMPLE_COUNT_32_BIT; break;
case 16: samples = VK_SAMPLE_COUNT_16_BIT; break;
case 8: samples = VK_SAMPLE_COUNT_8_BIT; break;
case 4: samples = VK_SAMPLE_COUNT_4_BIT; break;
case 2: samples = VK_SAMPLE_COUNT_2_BIT; break;
default: samples = VK_SAMPLE_COUNT_1_BIT; break;
}
VkPipelineMultisampleStateCreateInfo multisampleState = ext::vulkan::initializers::pipelineMultisampleStateCreateInfo(
samples,
0
);
if ( device.features.sampleRateShading ) {
multisampleState.sampleShadingEnable = VK_TRUE;
multisampleState.minSampleShading = 0.25f;
}
std::vector<VkDynamicState> dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
@ -1101,6 +1098,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descriptor ) {
//
if ( descriptorSet == VK_NULL_HANDLE ) return;
//descriptor = d;
// generate fallback empty texture
auto& emptyTexture = Texture2D::empty;
@ -1463,7 +1461,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescrip
pipeline.record(*this, commandBuffer, pass, draw);
// Bind triangle vertex buffer (contains position and colors)
VkDeviceSize offsets[1] = { 0 };
VkDeviceSize offsets[1] = { descriptor.offsets.vertex };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer->buffer, offsets);
// Bind triangle index buffer
VkIndexType indicesType = VK_INDEX_TYPE_UINT32;
@ -1475,9 +1473,10 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescrip
throw std::runtime_error("invalid indices size of " + std::to_string((int) descriptor.geometry.sizes.indices));
break;
}
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->buffer, 0, indicesType);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->buffer, descriptor.offsets.index, indicesType);
// Draw indexed triangle
vkCmdDrawIndexed(commandBuffer, descriptor.indices, 1, 0, 0, 1);
//std::cout << (int) descriptor.indices << "\t" << (int) descriptor.offsets.index << std::endl;
}
void ext::vulkan::Graphic::destroy() {
for ( auto& pair : pipelines ) pair.second.destroy();
@ -1545,6 +1544,13 @@ void ext::vulkan::GraphicDescriptor::parse( ext::json::Value& metadata ) {
cullMode = VK_CULL_MODE_FRONT_AND_BACK;
}
}
if ( metadata["indices"].is<size_t>() ) {
indices = metadata["indices"].as<size_t>();
}
if ( ext::json::isObject( metadata["offsets"] ) ) {
offsets.vertex = metadata["offsets"]["vertex"].as<size_t>();
offsets.index = metadata["offsets"]["index"].as<size_t>();
}
if ( ext::json::isObject(metadata["depth bias"]) ) {
depth.bias.enable = VK_TRUE;
depth.bias.constant = metadata["depth bias"]["constant"].as<float>();
@ -1557,9 +1563,13 @@ std::string ext::vulkan::GraphicDescriptor::hash() const {
serializer["subpass"] = subpass;
if ( settings::experimental::individualPipelines ) serializer["renderMode"] = renderMode;
serializer["renderTarget"] = renderTarget;
serializer["geometry"]["sizes"]["vertex"] = geometry.sizes.vertex;
serializer["geometry"]["sizes"]["indices"] = geometry.sizes.indices;
serializer["indices"] = indices;
serializer["offsets"]["vertex"] = offsets.vertex;
serializer["offsets"]["index"] = offsets.index;
{
int i = 0;

View File

@ -140,11 +140,11 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[i].view));
renderTarget.attachments[i].descriptor.format = ext::vulkan::settings::formats::color;
renderTarget.attachments[i].descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
renderTarget.attachments[i].descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
renderTarget.attachments[i].descriptor.aliased = true;
renderTarget.attachments[i].image = images[i];
renderTarget.attachments[i].format = ext::vulkan::settings::formats::color;
renderTarget.attachments[i].layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
renderTarget.attachments[i].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
renderTarget.attachments[i].aliased = true;
renderTarget.attachments[i].mem = VK_NULL_HANDLE;
}
// Create depth
@ -366,7 +366,7 @@ void ext::vulkan::BaseRenderMode::destroy() {
vkDestroyImageView( *device, attachment.view, nullptr);
attachment.view = VK_NULL_HANDLE;
}
if ( attachment.aliased ) continue;
if ( attachment.descriptor.aliased ) continue;
if ( attachment.image != VK_NULL_HANDLE ) {
// vkDestroyImage( *device, attachment.image, nullptr );
vmaDestroyImage( allocator, attachment.image, attachment.allocation );

View File

@ -36,31 +36,62 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
ext::vulkan::RenderMode::initialize( device );
{
renderTarget.device = &device;
renderTarget.samples = ext::vulkan::settings::msaa;
renderTarget.device = &device;
if ( !metadata["eyes"].is<size_t>() ) metadata["eyes"] = 1;
size_t eyes = metadata["eyes"].as<size_t>();
for ( size_t eye = 0; eye < eyes; ++eye ) {
struct {
size_t id, normals, uvs, albedo, depth, output;
} attachments;
size_t msaa = ext::vulkan::settings::msaa;
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
} else {
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
// Attach swapchain's image as output
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
attachments.output = renderTarget.attachments.size();
RenderTarget::Attachment swapchainAttachment;
swapchainAttachment.format = ext::vulkan::settings::formats::color; //device.formats.color;
swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.aliased = true;
auto& swapchainAttachment = renderTarget.attachments.emplace_back();
swapchainAttachment.descriptor.format = ext::vulkan::settings::formats::color; //device.formats.color;
swapchainAttachment.descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainAttachment.descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.descriptor.aliased = true;
{
VkBool32 blendEnabled = VK_TRUE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
@ -78,10 +109,17 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
swapchainAttachment.blendState = blendAttachmentState;
}
renderTarget.attachments.push_back(swapchainAttachment);
} else {
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
}
metadata["outputs"][eye] = attachments.output;
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
// First pass: fill the G-Buffer
{
@ -89,6 +127,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.id, attachments.normals, attachments.uvs },
{},
{},
attachments.depth
);
}
@ -98,6 +137,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.id, attachments.normals, attachments.uvs, attachments.depth },
{},
attachments.depth
);
}
@ -108,6 +148,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.id, attachments.normals, attachments.albedo },
{},
{},
attachments.depth
);
}
@ -117,142 +158,11 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.id, attachments.normals, attachments.albedo, attachments.depth },
{},
attachments.depth
);
}
}
/*
#if UF_VK_TESTING
struct {
size_t normals, uvs, id, depth, output;
} attachments;
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
#else
// attach targets
struct {
size_t normals, albedo, depth, output;
} attachments;
//VK_FORMAT_R16G16B16A16_SFLOAT
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
#endif
// Attach swapchain's image as output
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
attachments.output = renderTarget.attachments.size();
RenderTarget::Attachment swapchainAttachment;
swapchainAttachment.format = ext::vulkan::settings::formats::color; //device.formats.color;
swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.aliased = true;
{
VkBool32 blendEnabled = VK_TRUE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
writeMask,
blendEnabled
);
if ( blendEnabled == VK_TRUE ) {
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
}
swapchainAttachment.blendState = blendAttachmentState;
}
renderTarget.attachments.push_back(swapchainAttachment);
} else {
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
}
#if UF_VK_TESTING
// First pass: fill the G-Buffer
{
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.normals, attachments.uvs, attachments.id },
{},
attachments.depth
);
}
// Second pass: write to output
{
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.normals, attachments.uvs, attachments.id, attachments.depth },
attachments.depth
);
}
#else
// First pass: fill the G-Buffer
{
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.normals, attachments.albedo },
{},
attachments.depth
);
}
// Second pass: write to output
{
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.normals, attachments.albedo, attachments.depth },
attachments.depth
);
}
#endif
*/
/*
struct {
size_t albedo, normals, position, depth, output, ping, pong;
} attachments;
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
if ( !settings::experimental::deferredReconstructPosition )
attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
// attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
// attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
if ( settings::experimental::deferredReconstructPosition ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals },
{},
attachments.depth
);
} else {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, attachments.position },
{},
attachments.depth
);
}
// Second pass: write to output
if ( settings::experimental::deferredReconstructPosition ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.albedo, attachments.normals, attachments.depth },
attachments.depth
);
} else {
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.albedo, attachments.normals, attachments.position },
attachments.depth
);
}
*/
}
renderTarget.initialize( device );
@ -298,38 +208,40 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
std::vector<pod::DrawCall> drawCalls(specializationConstants.maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(specializationConstants.maxTextures);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
this->metadata["lightBufferIndex"] = blitter.initializeBuffer(
(void*) lights.data(),
lights.size() * sizeof(pod::Light::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["materialBufferIndex"] = blitter.initializeBuffer(
(void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["textureBufferIndex"] = blitter.initializeBuffer(
(void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["drawCallBufferIndex"] = blitter.initializeBuffer(
(void*) drawCalls.data(),
drawCalls.size() * sizeof(pod::DrawCall),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
drawCalls.size() * sizeof(pod::DrawCall::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
blitter.initializePipeline();
for ( size_t eye = 0; eye < eyes; ++eye ) {
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.subpass = 2 * eye + 1;
if ( blitter.hasPipeline( descriptor ) ) continue;
blitter.initializePipeline( descriptor );
}
}
}
void ext::vulkan::DeferredRenderMode::tick() {
@ -351,6 +263,8 @@ void ext::vulkan::DeferredRenderMode::destroy() {
void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
if ( !metadata["eyes"].is<size_t>() ) metadata["eyes"] = 1;
size_t eyes = metadata["eyes"].as<size_t>();
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -377,7 +291,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
std::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( !ext::json::isNull( metadata["system"]["renderer"]["clear values"][(int) clearValues.size()] ) ) {
auto& v = metadata["system"]["renderer"]["clear values"][(int) clearValues.size()];
clearValue.color = { {
@ -389,7 +303,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
} else {
clearValue.color = { { 0, 0, 0, 0 } };
}
} else if ( attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
}
clearValues.push_back(clearValue);
@ -426,40 +340,43 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
layer->pipelineBarrier( commands[i], 0 );
}
size_t currentPass = 0;
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
// render to geometry buffers
size_t currentDraw = 0;
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);
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
}
// blit any RT's that request this subpass
{
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
for ( size_t eye = 0; eye < eyes; ++eye ) {
size_t currentPass = 0;
size_t currentDraw = 0;
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);
graphic->record( commands[i], descriptor, eye, currentDraw++ );
}
// blit any RT's that request this subpass
{
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
blitter.record(commands[i]);
}
}
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass;
// deferred post-processing lighting pass
{
blitter.record(commands[i]);
}
}
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass;
// deferred post-processing lighting pass
{
blitter.record(commands[i]);
}
// blit any RT's that request this subpass
{
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
blitter.record(commands[i]);
// blit any RT's that request this subpass
{
for ( auto _ : layers ) {
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
auto& blitter = layer->blitter;
if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue;
blitter.record(commands[i]);
}
}
if ( eye + 1 < eyes ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
}
vkCmdEndRenderPass(commands[i]);
@ -512,19 +429,19 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
vkCmdBlitImage(
@ -542,19 +459,19 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
}
}

View File

@ -30,12 +30,12 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::initialize( Device& d
renderTarget.device = &device;
renderTarget.width = this->width;
renderTarget.height = this->height;
renderTarget.multiviews = 2;
renderTarget.views = 2;
// attach targets
struct {
size_t albedo, normals, position, depth, output;
} attachments;
#if 0
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
if ( !settings::experimental::deferredReconstructPosition )
@ -88,6 +88,7 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::initialize( Device& d
attachments.depth
);
}
#endif
renderTarget.initialize( device );
{
uf::BaseMesh<pod::Vertex_2F2F> mesh;
@ -187,7 +188,7 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::createCommandBuffers(
std::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( !ext::json::isNull( metadata["system"]["renderer"]["clear values"][(int) clearValues.size()] ) ) {
auto& v = metadata["system"]["renderer"]["clear values"][(int) clearValues.size()];
clearValue.color = { {
@ -199,7 +200,7 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::createCommandBuffers(
} else {
clearValue.color = { { 0, 0, 0, 0 } };
}
} else if ( attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
}
clearValues.push_back(clearValue);
@ -322,19 +323,19 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::createCommandBuffers(
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
vkCmdBlitImage(
@ -352,19 +353,19 @@ void ext::vulkan::MultiviewStereoscopicDeferredRenderMode::createCommandBuffers(
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
}
}

View File

@ -28,10 +28,19 @@ std::vector<ext::vulkan::Graphic*> ext::vulkan::RenderTargetRenderMode::getBlitt
ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
descriptor.parse(metadata["descriptor"]);
std::string type = metadata["type"].as<std::string>();
if ( type == "depth" ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
}
// allows for "easy" remapping for indices ranges
if ( ext::json::isObject( metadata["renderMode"]["target"][std::to_string(descriptor.indices)] ) ) {
auto& map = metadata["renderMode"]["target"][std::to_string(descriptor.indices)];
std::cout << "Replacing " << descriptor.indices;
descriptor.indices = map["size"].as<size_t>();
descriptor.offsets.index = map["offset"].as<size_t>();
std::cout << " with " << descriptor.offsets.index << " + " << descriptor.indices << std::endl;
}
return descriptor;
}
@ -49,11 +58,18 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
size_t depth;
} attachments;
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{},
{},
{},
attachments.depth
);
} else {
@ -62,11 +78,37 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
size_t albedo, normals, position, depth;
} attachments;
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::color,
/*.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,
/*.blend = */ true,
/*.samples = */ 1,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::normal,
/*.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,
/*.blend = */ false,
/*.samples = */ 1,
});
if ( !settings::experimental::deferredReconstructPosition )
attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::position,
/*.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,
/*.blend = */ false,
/*.samples = */ 1,
});
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::depth,
/*.layout = */ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
// First pass: write to target
if ( settings::experimental::deferredReconstructPosition ) {
@ -74,6 +116,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals },
{},
{},
attachments.depth
);
} else {
@ -81,6 +124,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, attachments.position },
{},
{},
attachments.depth
);
}
@ -138,7 +182,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
});
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
texture.aliasAttachment(attachment);
@ -152,7 +196,7 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
renderTarget.initialize( *renderTarget.device );
blitter.material.textures.clear();
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
texture.aliasAttachment(attachment);
}
@ -210,13 +254,13 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
if ( (attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
VkPipelineStageFlags srcStageMask, dstStageMask;
imageMemoryBarrier.image = attachment.image;
imageMemoryBarrier.oldLayout = attachment.layout;
imageMemoryBarrier.newLayout = attachment.layout;
imageMemoryBarrier.oldLayout = attachment.descriptor.layout;
imageMemoryBarrier.newLayout = attachment.descriptor.layout;
switch ( state ) {
case 0: {
@ -229,7 +273,7 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma
case 1: {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.newLayout = attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imageMemoryBarrier.newLayout = attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
} break;
@ -250,7 +294,7 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma
1, &imageMemoryBarrier
);
attachment.layout = imageMemoryBarrier.newLayout;
attachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
}
void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
@ -268,9 +312,9 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
std::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } };
} else if ( attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
}
clearValues.push_back(clearValue);

View File

@ -10,6 +10,7 @@
#include <uf/utils/camera/camera.h>
#include <uf/utils/math/transform.h>
#include <uf/ext/openvr/openvr.h>
#include <uf/ext/gltf/graph.h>
// ext::vulkan::StereoscopicDeferredRenderMode::StereoscopicDeferredRenderMode() : renderTargets({ renderTarget }), blitters({ blitter }) {
ext::vulkan::StereoscopicDeferredRenderMode::StereoscopicDeferredRenderMode() : renderTargets({ renderTarget }) {
@ -64,11 +65,105 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
renderTarget.device = &device;
renderTarget.width = this->width;
renderTarget.height = this->height;
struct {
size_t id, normals, uvs, albedo, depth, output;
} attachments;
size_t msaa = ext::vulkan::settings::msaa;
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.id, attachments.normals, attachments.uvs },
{},
{},
attachments.depth
);
}
// Second pass: write to output
{
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.id, attachments.normals, attachments.uvs, attachments.depth },
{},
attachments.depth
);
}
} else {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.id, attachments.normals, attachments.albedo },
{},
{},
attachments.depth
);
}
// Second pass: write to output
{
renderTarget.addPass(
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
{ attachments.output },
{ attachments.id, attachments.normals, attachments.albedo, attachments.depth },
{},
attachments.depth
);
}
}
#if 0
// attach targets
struct {
size_t albedo, normals, position, depth, output;
} attachments;
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
if ( !settings::experimental::deferredReconstructPosition )
@ -121,6 +216,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
attachments.depth
);
}
#endif
renderTarget.initialize( device );
{
uf::BaseMesh<pod::Vertex_2F2F> mesh;
@ -134,53 +230,62 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
0, 1, 2, 0, 2, 3
};
blitter.descriptor.subpass = 1;
blitter.descriptor.renderTarget = i++;
blitter.descriptor.depth.test = false;
blitter.descriptor.depth.write = false;
blitter.initialize( this->getName() );
blitter.initializeGeometry( mesh );
/*
if ( i == 0 ) {
blitter.material.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
// {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
{"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
} else {
blitter.material.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
}
*/
if ( settings::experimental::deferredReconstructPosition ) {
blitter.material.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
} else {
blitter.material.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
}
blitter.material.initializeShaders({
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
{
auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>();
auto& shader = blitter.material.shaders.back();
struct SpecializationConstant {
uint32_t maxLights = 16;
uint32_t maxTextures = 512;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
auto& metadata = scene.getComponent<uf::Serializer>();
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 )
binding.descriptorCount = specializationConstants.maxLights;
binding.descriptorCount = specializationConstants.maxTextures;
}
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(specializationConstants.maxTextures);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
this->metadata["lightBufferIndex"] = blitter.initializeBuffer(
(void*) lights.data(),
lights.size() * sizeof(pod::Light::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["materialBufferIndex"] = blitter.initializeBuffer(
(void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["textureBufferIndex"] = blitter.initializeBuffer(
(void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
this->metadata["drawCallBufferIndex"] = blitter.initializeBuffer(
(void*) drawCalls.data(),
drawCalls.size() * sizeof(pod::DrawCall::Storage),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
blitter.initializePipeline();
}
@ -258,7 +363,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
std::vector<VkClearValue> clearValues;
for ( auto& attachment : renderTarget.attachments ) {
VkClearValue clearValue;
if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) {
if ( !ext::json::isNull( metadata["system"]["renderer"]["clear values"][(int) clearValues.size()] ) ) {
auto& v = metadata["system"]["renderer"]["clear values"][(int) clearValues.size()];
clearValue.color = { {
@ -270,7 +375,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
} else {
clearValue.color = { { 0, 0, 0, 0 } };
}
} else if ( attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
} else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
clearValue.depthStencil = { 0.0f, 0 };
}
clearValues.push_back(clearValue);
@ -311,11 +416,12 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetViewport(commands[i], 0, 1, &viewport);
vkCmdSetScissor(commands[i], 0, 1, &scissor);
size_t currentDraw = 0;
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);
graphic->record( commands[i], descriptor, eyePass );
graphic->record( commands[i], descriptor, eyePass, currentDraw++ );
}
// render gui layer
{
@ -394,19 +500,19 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
vkCmdBlitImage(
@ -424,19 +530,19 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.layout;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.layout = imageMemoryBarrier.newLayout;
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
swapchainRender.renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout;
}
}
}

View File

@ -3,106 +3,94 @@
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& inputs, size_t depth ) {
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& inputs, const std::vector<size_t>& resolves, size_t depth ) {
Subpass pass;
pass.stage = stage;
pass.access = access;
for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
// for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
if ( depth < attachments.size() ) pass.depth = { (uint32_t) depth, attachments[depth].layout };
for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
for ( auto& i : resolves ) pass.resolves.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
// for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
if ( depth < attachments.size() ) pass.depth = { (uint32_t) depth, attachments[depth].descriptor.layout };
if ( !resolves.empty() && resolves.size() != colors.size() )
VK_VALIDATION_MESSAGE("Mismatching resolves count: Expecting " << colors.size() << ", got " << resolves.size());
passes.push_back(pass);
}
size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, bool blend, Attachment* attachment ) {
size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descriptor, Attachment* attachment ) {
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 ( !attachment ) {
attachments.resize(attachments.size()+1);
attachment = &attachments.back();
// no MSAA for depth
if ( false && usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
} else {
switch ( samples ) {
case 64: attachment->samples = VK_SAMPLE_COUNT_64_BIT; break;
case 32: attachment->samples = VK_SAMPLE_COUNT_32_BIT; break;
case 16: attachment->samples = VK_SAMPLE_COUNT_16_BIT; break;
case 8: attachment->samples = VK_SAMPLE_COUNT_8_BIT; break;
case 4: attachment->samples = VK_SAMPLE_COUNT_4_BIT; break;
case 2: attachment->samples = VK_SAMPLE_COUNT_2_BIT; break;
default: attachment->samples = VK_SAMPLE_COUNT_1_BIT; break;
}
}
} else {
if ( attachment ) {
if ( attachment->view ) {
vkDestroyImageView(*device, attachment->view, nullptr);
attachment->view = VK_NULL_HANDLE;
}
if ( attachment->image ) {
// vkDestroyImage(*device, attachment->image, nullptr);
vmaDestroyImage( allocator, attachment->image, attachment->allocation );
attachment->image = VK_NULL_HANDLE;
}
if ( attachment->mem ) {
// vkFreeMemory(*device, attachment->mem, nullptr);
attachment->mem = VK_NULL_HANDLE;
}
}
VkImageAspectFlags aspectMask = 0;
// specialization: depth buffer
if ( usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // | VK_IMAGE_ASPECT_STENCIL_BIT;
} else {
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachment = &attachments.emplace_back();
attachment->descriptor = descriptor;
}
// un-request transient attachments if not supported yet requested
if ( attachment->descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ) {
bool supported = false;
auto& properties = device->memoryProperties;
for ( uint32_t i = 0; i < properties.memoryTypeCount; ++i ) {
auto prop = properties.memoryTypes[i].propertyFlags;
if ( prop & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT ) {
supported = true;
}
}
if ( !supported ) {
VK_VALIDATION_MESSAGE("Transient attachment requested yet not supported, disabling...");
attachment->descriptor.usage &= ~VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
}
}
attachment->layout = layout;
attachment->format = format;
attachment->usage = usage;
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = format;
imageCreateInfo.format = attachment->descriptor.format;
imageCreateInfo.extent = { width, height, 1 };
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = this->multiviews;
imageCreateInfo.samples = attachment->samples;
imageCreateInfo.arrayLayers = this->views;
imageCreateInfo.samples = ext::vulkan::sampleCount( attachment->descriptor.samples );
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = usage;
imageCreateInfo.usage = attachment->descriptor.usage;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
if ( attachment->descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ) {
allocInfo.usage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;
}
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &attachment->image, &attachment->allocation, &attachment->allocationInfo));
attachment->mem = attachment->allocationInfo.deviceMemory;
/*
VK_CHECK_RESULT(vkCreateImage(*device, &imageCreateInfo, nullptr, &attachment->image));
// Allocate memory for the image (device local) and bind it to our image
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(*device, attachment->image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(*device, &memAlloc, nullptr, &attachment->mem));
VK_CHECK_RESULT(vkBindImageMemory(*device, attachment->image, attachment->mem, 0));
*/
// Create a view for the depth stencil image
// Images aren't directly accessed in Vulkan, but rather through views described by a subresource range
// This allows for multiple views of one image with differing ranges (e.g. for different layers)
VkImageAspectFlags aspectMask = 0;
// specialization: depth buffer
if ( attachment->descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // | VK_IMAGE_ASPECT_STENCIL_BIT;
} else {
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
VkImageViewCreateInfo imageView = {};
imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageView.format = format;
imageView.format = attachment->descriptor.format;
imageView.subresourceRange = {};
imageView.subresourceRange.aspectMask = aspectMask;
imageView.subresourceRange.baseMipLevel = 0;
imageView.subresourceRange.levelCount = 1;
imageView.subresourceRange.baseArrayLayer = 0;
imageView.subresourceRange.layerCount = this->multiviews;
imageView.subresourceRange.layerCount = this->views;
imageView.image = attachment->image;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
@ -111,7 +99,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
VkBool32 blendEnabled = VK_FALSE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
if ( blend ) {
if ( attachment->descriptor.blend ) {
blendEnabled = VK_TRUE;
writeMask |= VK_COLOR_COMPONENT_A_BIT;
}
@ -121,30 +109,6 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
blendEnabled
);
if ( blendEnabled == VK_TRUE ) {
/*
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
*/
/*
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
*/
/*
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
*/
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
@ -159,18 +123,15 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
}
void ext::vulkan::RenderTarget::initialize( Device& device ) {
// Bind
{
this->device = &device;
}
this->device = &device;
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
// resize attachments if necessary
if ( initialized ) {
for ( auto& attachment: this->attachments ) {
if ( attachment.aliased ) continue;
bool blend = attachment.blendState.blendEnable == VK_TRUE;
attach( attachment.format, attachment.usage, attachment.layout, blend, &attachment );
if ( attachment.descriptor.aliased ) continue;
attach( attachment.descriptor, &attachment );
}
}
// ensure attachments are already created
@ -182,14 +143,14 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
for ( auto& attachment : this->attachments ) {
VkAttachmentDescription description;
description.format = attachment.format;
description.samples = attachment.samples;
description.format = attachment.descriptor.format;
description.samples = ext::vulkan::sampleCount( attachment.descriptor.samples );
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
description.storeOp = attachment.descriptor.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
description.finalLayout = attachment.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.layout;
description.finalLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
description.flags = 0;
attachments.push_back(description);
@ -203,7 +164,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
// dependency: transition from final
VkSubpassDependency dependency;
dependency.dependencyFlags = 0; //VK_DEPENDENCY_BY_REGION_BIT;
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
@ -216,12 +177,12 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
description.colorAttachmentCount = pass.colors.size();
description.pColorAttachments = &pass.colors[0];
description.pDepthStencilAttachment = &pass.depth;
description.pResolveAttachments = &pass.resolves[0];
description.inputAttachmentCount = pass.inputs.size();
description.pInputAttachments = &pass.inputs[0];
description.pDepthStencilAttachment = &pass.depth;
description.preserveAttachmentCount = 0;
description.pPreserveAttachments = nullptr;
description.pResolveAttachments = nullptr;
description.flags = 0;
for ( auto& input : pass.inputs ) {
if ( input.attachment == pass.depth.attachment ) {
@ -275,7 +236,6 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
{
VkSubpassDependency dependency;
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependency.srcSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
@ -309,7 +269,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
/*
uint32_t mask = 0;
std::vector<uint32_t> masks;
for ( size_t i = 0; i < this->multiviews; ++i ) {
for ( size_t i = 0; i < this->views; ++i ) {
mask |= (0b00000001 << i);
}
for ( size_t i = 0; i < static_cast<uint32_t>(descriptions.size()); ++i ) {
@ -322,7 +282,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
renderPassMultiviewInfo.pViewMasks = masks.data();
renderPassMultiviewInfo.pCorrelationMasks = masks.data();
renderPassMultiviewInfo.correlationMaskCount = 1;
if ( this->multiviews > 1 ) {
if ( this->views > 1 ) {
renderPassInfo.pNext = &renderPassMultiviewInfo;
}
*/
@ -340,7 +300,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
for ( size_t i = 0; i < framebuffers.size(); ++i ) {
std::vector<VkImageView> attachments;
for ( auto& attachment : this->attachments ) {
if ( attachment.aliased && attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
if ( attachment.descriptor.aliased && attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachments.push_back(base.renderTarget.attachments[i].view);
} else attachments.push_back(attachment.view);
}
@ -367,7 +327,7 @@ void ext::vulkan::RenderTarget::destroy() {
for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( *device, framebuffer, nullptr );
for ( auto& attachment : attachments ) {
if ( attachment.aliased ) continue;
if ( attachment.descriptor.aliased ) continue;
vkDestroyImageView( *device, attachment.view, nullptr );
attachment.view = VK_NULL_HANDLE;
// vkDestroyImage( *device, attachment.image, nullptr );

View File

@ -49,6 +49,38 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig
this->height = height;
this->depth = depth;
this->layers = layers;
// implicitly set type
if ( width > 1 && height > 1 && depth > 1 ) {
this->type = VK_IMAGE_TYPE_3D;
} else if ( (width == 1 && height > 1 && depth > 1) || (width > 1 && height == 1 && depth > 1) || (width > 1 && height > 1 && depth == 1) ) {
this->type = VK_IMAGE_TYPE_2D;
} else if ( (width > 1 && height == 1 && depth == 1) || (width == 1 && height > 1 && depth == 1) || (width == 1 && height == 1 && depth > 1) ) {
this->type = VK_IMAGE_TYPE_1D;
}
if ( depth > 1 ) {
if ( viewType == VK_IMAGE_VIEW_TYPE_1D ) viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
if ( viewType == VK_IMAGE_VIEW_TYPE_2D ) viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
if ( viewType == VK_IMAGE_VIEW_TYPE_CUBE ) viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
}
}
void ext::vulkan::Texture::initialize( Device& device, VkImageViewType viewType, size_t width, size_t height, size_t depth, size_t layers ) {
this->initialize( device, width, height, depth, layers );
this->viewType = viewType;
switch ( viewType ) {
case VK_IMAGE_VIEW_TYPE_1D:
case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
type = VK_IMAGE_TYPE_1D;
break;
case VK_IMAGE_VIEW_TYPE_2D:
case VK_IMAGE_VIEW_TYPE_CUBE:
case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
type = VK_IMAGE_TYPE_2D;
break;
case VK_IMAGE_VIEW_TYPE_3D:
type = VK_IMAGE_TYPE_3D;
break;
}
}
void ext::vulkan::Texture::updateDescriptors() {
descriptor.sampler = sampler.sampler;
@ -70,11 +102,11 @@ void ext::vulkan::Texture::destroy() {
vmaDestroyImage( allocator, image, allocation );
image = VK_NULL_HANDLE;
}
sampler.destroy();
if ( deviceMemory != VK_NULL_HANDLE ) {
// vkFreeMemory(device->logicalDevice, deviceMemory, nullptr);
deviceMemory = VK_NULL_HANDLE;
}
sampler.destroy();
}
void ext::vulkan::Texture::setImageLayout(
VkCommandBuffer cmdbuffer,
@ -188,7 +220,6 @@ void ext::vulkan::Texture::setImageLayout(
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
// Put barrier inside setup command buffer
vkCmdPipelineBarrier(
cmdbuffer,
@ -214,7 +245,7 @@ void ext::vulkan::Texture::setImageLayout(
subresourceRange.layerCount = 1;
setImageLayout(cmdbuffer, image, oldImageLayout, newImageLayout, subresourceRange);
}
void ext::vulkan::Texture2D::loadFromFile(
void ext::vulkan::Texture::loadFromFile(
std::string filename,
VkFormat format,
VkImageUsageFlags imageUsageFlags,
@ -222,7 +253,7 @@ void ext::vulkan::Texture2D::loadFromFile(
) {
return loadFromFile( filename, ext::vulkan::device, format, imageUsageFlags, imageLayout );
}
void ext::vulkan::Texture2D::loadFromFile(
void ext::vulkan::Texture::loadFromFile(
std::string filename,
Device& device,
VkFormat format,
@ -298,7 +329,7 @@ void ext::vulkan::Texture2D::loadFromFile(
imageLayout
);
}
void ext::vulkan::Texture2D::loadFromImage(
void ext::vulkan::Texture::loadFromImage(
uf::Image& image,
VkFormat format,
VkImageUsageFlags imageUsageFlags,
@ -306,7 +337,7 @@ void ext::vulkan::Texture2D::loadFromImage(
) {
return loadFromImage( image, ext::vulkan::device, format, imageUsageFlags, imageLayout );
}
void ext::vulkan::Texture2D::loadFromImage(
void ext::vulkan::Texture::loadFromImage(
uf::Image& image,
Device& device,
VkFormat format,
@ -369,7 +400,7 @@ void ext::vulkan::Texture2D::loadFromImage(
);
}
void ext::vulkan::Texture2D::fromBuffers(
void ext::vulkan::Texture::fromBuffers(
void* data,
VkDeviceSize bufferSize,
VkFormat format,
@ -383,8 +414,9 @@ void ext::vulkan::Texture2D::fromBuffers(
) {
this->initialize(device, texWidth, texHeight, texDepth, layers);
if ( this->depth > 1 ) this->mips = 1; else
{
if ( this->mips == 0 ) {
this->mips = 1;
} else if ( this->depth == 1 ) {
this->mips = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, &formatProperties);
@ -396,7 +428,7 @@ void ext::vulkan::Texture2D::fromBuffers(
// Create optimal tiled target image
VkImageCreateInfo imageCreateInfo = ext::vulkan::initializers::imageCreateInfo();
imageCreateInfo.imageType = this->depth > 1 ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
imageCreateInfo.imageType = this->type;
imageCreateInfo.format = this->format = format;
imageCreateInfo.mipLevels = this->mips;
imageCreateInfo.arrayLayers = this->layers;
@ -414,6 +446,10 @@ void ext::vulkan::Texture2D::fromBuffers(
if (!(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
// Ensure cube maps get the compat flag bit
if ( this->viewType == VK_IMAGE_VIEW_TYPE_CUBE || this->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ) {
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
@ -425,21 +461,17 @@ void ext::vulkan::Texture2D::fromBuffers(
sampler.descriptor.mip.max = static_cast<float>(this->mips);
sampler.initialize( device );
// Create image view
VkImageSubresourceRange subresourceRange = {};
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = this->mips;
subresourceRange.layerCount = this->layers;
// Create image view
VkImageViewCreateInfo viewCreateInfo = {};
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewCreateInfo.pNext = NULL;
viewCreateInfo.viewType = this->depth > 1 ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
viewCreateInfo.viewType = viewType;
viewCreateInfo.format = format;
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
viewCreateInfo.subresourceRange.levelCount = 1;
viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewCreateInfo.subresourceRange.baseMipLevel = 0;
viewCreateInfo.subresourceRange.layerCount = this->layers;
viewCreateInfo.subresourceRange.levelCount = this->mips;
viewCreateInfo.image = image;
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
@ -455,7 +487,7 @@ void ext::vulkan::Texture2D::fromBuffers(
this->updateDescriptors();
}
void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uint32_t height, VkFormat format ) {
void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint32_t height, VkFormat format ) {
// Prepare blit target texture
this->initialize( device, width, height );
@ -466,7 +498,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
VkImageCreateInfo imageCreateInfo = ext::vulkan::initializers::imageCreateInfo();
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.imageType = type;
imageCreateInfo.format = format;
imageCreateInfo.extent = { width, height, depth };
imageCreateInfo.mipLevels = this->mips = 1;
@ -505,7 +537,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
// Create image view
VkImageViewCreateInfo viewCreateInfo = ext::vulkan::initializers::imageViewCreateInfo();
viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewCreateInfo.viewType = viewType;
viewCreateInfo.format = format;
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
@ -515,7 +547,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
// Initialize a descriptor for later use
this->updateDescriptors();
}
void ext::vulkan::Texture2D::aliasTexture( const Texture2D& texture ) {
void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
image = texture.image;
view = texture.view;
imageLayout = texture.imageLayout;
@ -524,10 +556,10 @@ void ext::vulkan::Texture2D::aliasTexture( const Texture2D& texture ) {
this->updateDescriptors();
}
void ext::vulkan::Texture2D::aliasAttachment( const RenderTarget::Attachment& attachment, bool createSampler ) {
void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& attachment, bool createSampler ) {
image = attachment.image;
view = attachment.view;
imageLayout = attachment.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : attachment.layout;
imageLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
deviceMemory = attachment.mem;
// Create sampler
@ -536,13 +568,12 @@ void ext::vulkan::Texture2D::aliasAttachment( const RenderTarget::Attachment& at
this->updateDescriptors();
}
void ext::vulkan::Texture2D::update( uf::Image& image, VkImageLayout targetImageLayout, uint32_t layer ) {
if ( width != image.getDimensions()[0] || height != image.getDimensions()[1] )
return;
void ext::vulkan::Texture::update( uf::Image& image, VkImageLayout targetImageLayout, uint32_t layer ) {
if ( width != image.getDimensions()[0] || height != image.getDimensions()[1] ) return;
return this->update( (void*) image.getPixelsPtr(), image.getPixels().size(), layer );
}
void ext::vulkan::Texture2D::update( void* data, VkDeviceSize bufferSize, VkImageLayout targetImageLayout, uint32_t layer ) {
// Update descriptor image info member that can be used for setting up descriptor sets
void ext::vulkan::Texture::update( void* data, VkDeviceSize bufferSize, VkImageLayout targetImageLayout, uint32_t layer ) {
// Update descriptor image info member that can be used for setting up descriptor sets
auto& device = *this->device;
@ -617,7 +648,7 @@ void ext::vulkan::Texture2D::update( void* data, VkDeviceSize bufferSize, VkImag
this->updateDescriptors();
}
void ext::vulkan::Texture2D::generateMipmaps( VkCommandBuffer commandBuffer, uint32_t layer ) {
void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint32_t layer ) {
auto& device = *this->device;
if ( this->mips <= 1 ) return;
@ -694,4 +725,17 @@ void ext::vulkan::Texture2D::generateMipmaps( VkCommandBuffer commandBuffer, uin
if (mipHeight > 1) mipHeight /= 2;
if (mipDepth > 1) mipDepth /= 2;
}
}
ext::vulkan::Texture2D::Texture2D() {
type = VK_IMAGE_TYPE_2D;
viewType = VK_IMAGE_VIEW_TYPE_2D;
}
ext::vulkan::Texture3D::Texture3D() {
type = VK_IMAGE_TYPE_3D;
viewType = VK_IMAGE_VIEW_TYPE_3D;
}
ext::vulkan::TextureCube::TextureCube() {
type = VK_IMAGE_TYPE_2D;
viewType = VK_IMAGE_VIEW_TYPE_CUBE;
}

View File

@ -113,20 +113,18 @@ std::string ext::vulkan::errorString( VkResult result ) {
return "UNKNOWN_ERROR";
}
}
uint32_t ext::vulkan::getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) {
// Iterate over all memory types available for the device used in this example
for (uint32_t i = 0; i < ext::vulkan::device.memoryProperties.memoryTypeCount; i++) {
if ((typeBits & 1) == 1) {
if ((ext::vulkan::device.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
typeBits >>= 1;
}
throw std::runtime_error("Could not find a suitable memory type!");
VkSampleCountFlagBits ext::vulkan::sampleCount( uint8_t count ) {
VkSampleCountFlags counts = std::min(ext::vulkan::device.properties.limits.framebufferColorSampleCounts, ext::vulkan::device.properties.limits.framebufferDepthSampleCounts);
if ( count < counts ) counts = count;
if ( counts & VK_SAMPLE_COUNT_64_BIT ) return VK_SAMPLE_COUNT_64_BIT;
if ( counts & VK_SAMPLE_COUNT_32_BIT ) return VK_SAMPLE_COUNT_32_BIT;
if ( counts & VK_SAMPLE_COUNT_16_BIT ) return VK_SAMPLE_COUNT_16_BIT;
if ( counts & VK_SAMPLE_COUNT_8_BIT ) return VK_SAMPLE_COUNT_8_BIT;
if ( counts & VK_SAMPLE_COUNT_4_BIT ) return VK_SAMPLE_COUNT_4_BIT;
if ( counts & VK_SAMPLE_COUNT_2_BIT ) return VK_SAMPLE_COUNT_2_BIT;
return VK_SAMPLE_COUNT_1_BIT;
}
void* ext::vulkan::alignedAlloc( size_t size, size_t alignment ) {
void *data = nullptr;
#if defined(_MSC_VER) || defined(__MINGW32__)
@ -211,21 +209,6 @@ void ext::vulkan::initialize( uint8_t stage ) {
case 0: {
device.initialize();
swapchain.initialize( device );
{
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = device.physicalDevice;
allocatorInfo.device = device.logicalDevice;
vmaCreateAllocator(&allocatorInfo, &allocator);
}
{
std::vector<uint8_t> pixels = {
255, 0, 255, 255, 0, 0, 0, 255,
0, 0, 0, 255, 255, 0, 255, 255,
};
Texture2D::empty.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
Texture2D::empty.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
Texture2D::empty.fromBuffers( (void*) &pixels[0], pixels.size(), VK_FORMAT_R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT );
}
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->initialize(device);
@ -246,12 +229,15 @@ void ext::vulkan::initialize( uint8_t stage ) {
if ( !jobs.empty() ) {
uf::thread::batchWorkers( jobs );
}
/*
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->createCommandBuffers();
{
std::vector<uint8_t> pixels = {
255, 0, 255, 255, 0, 0, 0, 255,
0, 0, 0, 255, 255, 0, 255, 255,
};
Texture2D::empty.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
Texture2D::empty.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
Texture2D::empty.fromBuffers( (void*) &pixels[0], pixels.size(), VK_FORMAT_R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT );
}
*/
} break;
case 1: {
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
@ -400,8 +386,6 @@ void ext::vulkan::destroy() {
renderMode = NULL;
}
vmaDestroyAllocator( allocator );
swapchain.destroy();
device.destroy();
ext::vulkan::mutex.unlock();

View File

@ -70,14 +70,14 @@ std::string uf::Image::getFilename() const {
}
// from file
bool uf::Image::open( const std::string& filename ) {
bool uf::Image::open( const std::string& filename, bool flip ) {
if ( !uf::io::exists(filename) ) throw std::runtime_error("does not exist: " + filename);
this->m_filename = filename;
this->m_pixels.clear();
std::string extension = uf::io::extension(filename);
#if 0
if ( extension == "png" ) {
uint mode = 2;
#if 0
png_byte header[8];
FILE* file = fopen(filename.c_str(), "rb");
@ -170,42 +170,43 @@ bool uf::Image::open( const std::string& filename ) {
// this->convert(uf::Image::Format::RGBA, 32);
}
*/
#else
int width, height, channels, bit_depth;
bit_depth = 8;
stbi_set_flip_vertically_on_load(true);
unsigned char* buffer = stbi_load(
filename.c_str(),
&width,
&height,
&channels,
STBI_rgb_alpha
);
channels = 4;
uint len = width * height * channels;
this->m_dimensions.x = width;
this->m_dimensions.y = height;
this->m_bpp = bit_depth * channels;
this->m_channels = channels;
this->m_pixels.insert( this->m_pixels.end(), (uint8_t*) buffer, buffer + len );
/*
if ( this->m_channels != 4 ) {
std::string from = "";
switch ( this->m_channels ) {
case 1: from = "r"; break;
case 2: from = "ra"; break;
case 3: from = "rgb"; break;
}
this->convert(from);
}
std::cout << "Hash of " << filename << ": " << uf::string::sha256( uf::io::readAsBuffer(filename) ) << std::endl;
*/
stbi_image_free(buffer);
#endif
return true;
}
return true;
#else
int width, height, channels, bit_depth;
bit_depth = 8;
stbi_set_flip_vertically_on_load(true);
unsigned char* buffer = stbi_load(
filename.c_str(),
&width,
&height,
&channels,
STBI_rgb_alpha
);
channels = 4;
uint len = width * height * channels;
this->m_dimensions.x = width;
this->m_dimensions.y = height;
this->m_bpp = bit_depth * channels;
this->m_channels = channels;
this->m_pixels.insert( this->m_pixels.end(), (uint8_t*) buffer, buffer + len );
/*
if ( this->m_channels != 4 ) {
std::string from = "";
switch ( this->m_channels ) {
case 1: from = "r"; break;
case 2: from = "ra"; break;
case 3: from = "rgb"; break;
}
this->convert(from);
}
std::cout << "Hash of " << filename << ": " << uf::string::sha256( uf::io::readAsBuffer(filename) ) << std::endl;
*/
stbi_image_free(buffer);
return true;
#endif
}
void uf::Image::loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod::Vector2ui& size, std::size_t bit_depth, std::size_t channels, bool flip ) {
this->m_dimensions = size;

View File

@ -63,6 +63,8 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
renderMode.metadata["type"] = "depth";
renderMode.metadata["depth bias"] = metadata["light"]["bias"];
renderMode.metadata["renderMode"] = metadata["renderMode"];
// std::cout << this->getName() << ": " << renderMode.metadata["renderMode"] << std::endl;
if ( metadata["light"]["type"].as<std::string>() == "point" ) {
metadata["light"]["fov"] = 90.0f;

View File

@ -130,7 +130,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
// initialize perlin noise
{
auto& texture = this->getComponent<uf::renderer::Texture2D>();
auto& texture = this->getComponent<uf::renderer::Texture3D>();
texture.sampler.descriptor.addressMode = {
VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
@ -173,6 +173,41 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
}
texture.fromBuffers( (void*) pixels.data(), pixels.size(), VK_FORMAT_R8_UNORM, size.x, size.y, size.z, 1, ext::vulkan::device );
}
// initialize cubemap
{
std::vector<std::string> filenames = {
"./data/textures/skybox/front.png",
"./data/textures/skybox/back.png",
"./data/textures/skybox/up.png",
"./data/textures/skybox/down.png",
"./data/textures/skybox/right.png",
"./data/textures/skybox/left.png",
};
uf::Image::container_t pixels;
std::vector<uf::Image> images(filenames.size());
pod::Vector2ui size = {0,0};
auto& texture = this->getComponent<uf::renderer::TextureCube>();
for ( size_t i = 0; i < filenames.size(); ++i ) {
auto& filename = filenames[i];
auto& image = images[i];
image.open(filename);
image.flip();
if ( size.x == 0 && size.y == 0 ) {
size = image.getDimensions();
} else if ( size != image.getDimensions() ) {
std::cout << "ERROR: MISMATCH CUBEMAP FACE SIZE" << std::endl;
}
auto& p = image.getPixels();
pixels.reserve( pixels.size() + p.size() );
pixels.insert( pixels.end(), p.begin(), p.end() );
}
texture.mips = 0;
texture.fromBuffers( (void*) pixels.data(), pixels.size(), VK_FORMAT_R8G8B8A8_UNORM, size.x, size.y, 1, filenames.size(), ext::vulkan::device );
}
}
void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
@ -294,6 +329,9 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
struct Matrices {
alignas(16) pod::Matrix4f view[2];
alignas(16) pod::Matrix4f projection[2];
alignas(16) pod::Matrix4f iView[2];
alignas(16) pod::Matrix4f iProjection[2];
alignas(16) pod::Matrix4f iProjectionView[2];
} matrices;
struct Mode {
alignas(8) pod::Vector2ui type;
@ -320,6 +358,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
alignas(4) uint32_t drawCalls = 0;
} lengths;
alignas(16) pod::Vector4f ambient;
// alignas(16) pod::Vector4f position;
};
struct SpecializationConstant {
uint32_t maxTextures = 512;
@ -334,7 +373,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
};
std::vector<LightInfo> entities;
std::vector<pod::Graph*> graphs;
// std::vector<uf::Entity*> graphs;
this->process([&]( uf::Entity* entity ) { if ( !entity ) return;
auto& metadata = entity->getComponent<uf::Serializer>();
@ -405,9 +443,21 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms->matrices.view[i] = camera.getView( i );
uniforms->matrices.projection[i] = camera.getProjection( i );
uniforms->matrices.iView[i] = uf::matrix::inverse( uniforms->matrices.view[i] );
uniforms->matrices.iProjection[i] = uf::matrix::inverse( uniforms->matrices.projection[i] );
uniforms->matrices.iProjectionView[i] = uf::matrix::inverse( uniforms->matrices.projection[i] * uniforms->matrices.view[i] );
}
uniforms->ambient = uf::vector::decode( metadata["light"]["ambient"], uniforms->ambient );
/*
pod::Transform<> transform = controller.getComponent<pod::Transform<>>();
if ( controller.hasComponent<uf::Camera>() ) {
auto& camera = controller.getComponent<uf::Camera>();
transform.position += camera.getTransform().position;
transform = uf::transform::reorient( transform );
}
uniforms->position = transform.position;
*/
uniforms->fog.color = uf::vector::decode( metadata["light"]["fog"]["color"], uniforms->fog.color );
uniforms->fog.color.w = metadata["light"]["fog"]["step scale"].as<float>();
@ -435,7 +485,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
graphic.material.textures.clear();
// add noise texture
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::Texture2D>());
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::Texture3D>());
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::TextureCube>());
size_t updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as<size_t>();
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
@ -451,7 +502,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
std::vector<pod::Texture::Storage> textures;
textures.reserve(maxTextures);
std::vector<pod::DrawCall> drawCalls;
std::vector<pod::DrawCall::Storage> drawCalls;
drawCalls.reserve(maxTextures);
// add materials
@ -459,7 +510,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
for ( auto* entity : graphs ) {
auto& graph = *entity;
drawCalls.emplace_back(pod::DrawCall{
drawCalls.emplace_back(pod::DrawCall::Storage{
materials.size(),
graph.materials.size(),
textures.size(),
@ -518,8 +569,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
size_t view = 0;
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
graphic.material.textures.emplace_back().aliasAttachment(attachment);
@ -552,7 +603,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
graphic.updateBuffer( (void*) lights.data(), uniforms->lengths.lights * sizeof(pod::Light::Storage), lightBufferIndex, false );
graphic.updateBuffer( (void*) materials.data(), uniforms->lengths.materials * sizeof(pod::Material::Storage), materialBufferIndex, false );
graphic.updateBuffer( (void*) textures.data(), uniforms->lengths.textures * sizeof(pod::Texture::Storage), textureBufferIndex, false );
graphic.updateBuffer( (void*) drawCalls.data(), uniforms->lengths.drawCalls * sizeof(pod::DrawCall), drawCallBufferIndex, false );
graphic.updateBuffer( (void*) drawCalls.data(), uniforms->lengths.drawCalls * sizeof(pod::DrawCall::Storage), drawCallBufferIndex, false );
graphic.updatePipelines();
}

View File

@ -379,20 +379,28 @@ void EXT_API ext::initialize() {
uf::renderer::addRenderMode( renderMode, "Gui" );
renderMode->blitter.descriptor.subpass = 1;
}
/*
if ( ::config["engine"]["render modes"]["multiview stereo deferred"].as<bool>() )
uf::renderer::addRenderMode( new uf::renderer::MultiviewStereoscopicDeferredRenderMode, "" );
else if ( ::config["engine"]["render modes"]["stereo deferred"].as<bool>() )
uf::renderer::addRenderMode( new uf::renderer::StereoscopicDeferredRenderMode, "" );
else if ( ::config["engine"]["render modes"]["deferred"].as<bool>() )
uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" );
*/
if ( ::config["engine"]["render modes"]["deferred"].as<bool>() ) {
uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" );
if ( ::config["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
renderMode.metadata["eyes"] = 2;
}
}
if ( ext::openvr::enabled ) {
ext::openvr::initialize();
uint32_t width, height;
ext::openvr::recommendedResolution( width, height );
auto& renderMode = uf::renderer::getRenderMode("Stereoscopic Deferred", true);
auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
renderMode.width = width;
renderMode.height = height;
@ -678,6 +686,15 @@ void EXT_API ext::terminate() {
uf::scene::destroy();
/* Garbage collection */ if ( false ) {
uint8_t mode = ::config["engine"]["debug"]["garbage collection"]["mode"].as<uint64_t>();
bool announce = ::config["engine"]["debug"]["garbage collection"]["announce"].as<bool>();
size_t collected = uf::instantiator::collect( mode );
if ( announce && collected > 0 ) {
uf::iostream << "GC collected " << (int) collected << " unused entities" << "\n";
}
}
/* Close vulkan */ {
uf::renderer::destroy();
}

View File

@ -68,9 +68,7 @@ void ext::RayTracingSceneBehavior::initialize( uf::Object& self ) {
renderMode.compute.initializeBuffer(
(void*) shapes.data(),
shapes.size() * sizeof(Shape),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
true
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}
}