diff --git a/extensions/pl_graphics_ext.c b/extensions/pl_graphics_ext.c index 46fc5b20..66fe072b 100644 --- a/extensions/pl_graphics_ext.c +++ b/extensions/pl_graphics_ext.c @@ -677,6 +677,7 @@ pl__cleanup_common_graphics(plGraphics* ptGraphics) pl_sb_free(ptGraphics->tSwapchain.sbtSwapchainTextureViews); pl_sb_free(ptGraphics->sbtShadersCold); pl_sb_free(ptGraphics->sbtBuffersCold); + pl_sb_free(ptGraphics->sbtShaderFreeIndices); pl_sb_free(ptGraphics->sbtBufferFreeIndices); pl_sb_free(ptGraphics->sbtTexturesCold); pl_sb_free(ptGraphics->sbtSamplersCold); diff --git a/extensions/pl_vulkan_ext.c b/extensions/pl_vulkan_ext.c index 23ac4fd2..fd607f70 100644 --- a/extensions/pl_vulkan_ext.c +++ b/extensions/pl_vulkan_ext.c @@ -1380,6 +1380,9 @@ pl_create_bind_group_layout(plDevice* ptDevice, plBindGroupLayout* ptLayout, con }; PL_VULKAN(vkCreateDescriptorSetLayout(ptVulkanDevice->tLogicalDevice, &tDescriptorSetLayoutInfo, NULL, &tVulkanBindGroupLayout.tDescriptorSetLayout)); + if(pcName) + pl_set_vulkan_object_name(ptDevice, (uint64_t)tVulkanBindGroupLayout.tDescriptorSetLayout, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, pcName); + ptVulkanGraphics->sbtBindGroupLayouts[uBindGroupLayoutIndex] = tVulkanBindGroupLayout; pl_temp_allocator_reset(&ptVulkanGraphics->tTempAllocator); } @@ -5614,7 +5617,7 @@ pl__garbage_collect(plGraphics* ptGraphics) ptVariantVulkanResource->tPipelineLayout = VK_NULL_HANDLE; ptVariantVulkanResource->tPipeline = VK_NULL_HANDLE; pl_sb_push(ptGraphics->sbtShaderFreeIndices, iResourceIndex); - for(uint32_t k = 0; k < ptResource->tDescription.uBindGroupLayoutCount + 1; k++) + for(uint32_t k = 0; k < ptResource->tDescription.uBindGroupLayoutCount; k++) { plVulkanBindGroupLayout* ptVulkanBindGroupLayout = &ptVulkanGfx->sbtBindGroupLayouts[ptResource->tDescription.atBindGroupLayouts[k].uHandle]; vkDestroyDescriptorSetLayout(ptVulkanDevice->tLogicalDevice, ptVulkanBindGroupLayout->tDescriptorSetLayout, NULL); @@ -5640,7 +5643,7 @@ pl__garbage_collect(plGraphics* ptGraphics) ptVariantVulkanResource->tPipeline = VK_NULL_HANDLE; pl_sb_push(ptGraphics->sbtComputeShaderFreeIndices, iResourceIndex); - for(uint32_t k = 0; k < ptResource->tDescription.uBindGroupLayoutCount + 1; k++) + for(uint32_t k = 0; k < ptResource->tDescription.uBindGroupLayoutCount; k++) { plVulkanBindGroupLayout* ptVulkanBindGroupLayout = &ptVulkanGfx->sbtBindGroupLayouts[ptResource->tDescription.atBindGroupLayouts[k].uHandle]; vkDestroyDescriptorSetLayout(ptVulkanDevice->tLogicalDevice, ptVulkanBindGroupLayout->tDescriptorSetLayout, NULL); diff --git a/scripts/gen_build.py b/scripts/gen_build.py index 12a8192b..6135afe4 100644 --- a/scripts/gen_build.py +++ b/scripts/gen_build.py @@ -157,7 +157,9 @@ def add_plugin_to_metal_app(name, reloadable, objc = False, binary_name = None): "draw_3d_line.vert", "panorama_to_cubemap.comp", "filter_environment.comp", - "skinning.comp" + "skinning.comp", + "outline.vert", + "outline.frag", ] metal_shaders = [ @@ -169,7 +171,8 @@ def add_plugin_to_metal_app(name, reloadable, objc = False, binary_name = None): "skybox.metal", "filter_environment.metal", "transparent.metal", - "skinning.metal" + "skinning.metal", + "outline.metal" ] with pl.target("app", pl.TargetType.DYNAMIC_LIBRARY, True): diff --git a/shaders/glsl/outline.frag b/shaders/glsl/outline.frag new file mode 100644 index 00000000..0bf917a4 --- /dev/null +++ b/shaders/glsl/outline.frag @@ -0,0 +1,52 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +//----------------------------------------------------------------------------- +// [SECTION] specialication constants +//----------------------------------------------------------------------------- + +layout(constant_id = 0) const int iMeshVariantFlags = 0; +layout(constant_id = 1) const int iDataStride = 0; + +//----------------------------------------------------------------------------- +// [SECTION] bind group 0 +//----------------------------------------------------------------------------- + +layout(set = 0, binding = 0) uniform _plGlobalInfo +{ + vec4 tCameraPos; + mat4 tCameraView; + mat4 tCameraProjection; + mat4 tCameraViewProjection; +} tGlobalInfo; + +layout(std140, set = 0, binding = 1) readonly buffer _tVertexBuffer +{ + vec4 atVertexData[]; +} tVertexBuffer; + +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +layout(set = 1, binding = 0) uniform _plObjectInfo +{ + vec4 tColor; + float fThickness; + int iDataOffset; + int iVertexOffset; + mat4 tModel; +} tObjectInfo; + +//----------------------------------------------------------------------------- +// [SECTION] entry +//----------------------------------------------------------------------------- + +// output +layout(location = 0) out vec4 outColor; + +void +main() +{ + outColor = tObjectInfo.tColor; +} \ No newline at end of file diff --git a/shaders/glsl/outline.vert b/shaders/glsl/outline.vert new file mode 100644 index 00000000..a445b528 --- /dev/null +++ b/shaders/glsl/outline.vert @@ -0,0 +1,73 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +//----------------------------------------------------------------------------- +// [SECTION] specialication constants +//----------------------------------------------------------------------------- + +layout(constant_id = 0) const int iMeshVariantFlags = 0; +layout(constant_id = 1) const int iDataStride = 0; + +//----------------------------------------------------------------------------- +// [SECTION] defines +//----------------------------------------------------------------------------- + +// iMeshVariantFlags +const int PL_MESH_FORMAT_FLAG_HAS_POSITION = 1 << 0; +const int PL_MESH_FORMAT_FLAG_HAS_NORMAL = 1 << 1; + +//----------------------------------------------------------------------------- +// [SECTION] bind group 0 +//----------------------------------------------------------------------------- + +layout(set = 0, binding = 0) uniform _plGlobalInfo +{ + vec4 tCameraPos; + mat4 tCameraView; + mat4 tCameraProjection; + mat4 tCameraViewProjection; +} tGlobalInfo; + +layout(std140, set = 0, binding = 1) readonly buffer _tVertexBuffer +{ + vec4 atVertexData[]; +} tVertexBuffer; + +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +layout(set = 1, binding = 0) uniform _plObjectInfo +{ + vec4 tColor; + float fThickness; + int iDataOffset; + int iVertexOffset; + mat4 tModel; +} tObjectInfo; + +//----------------------------------------------------------------------------- +// [SECTION] entry +//----------------------------------------------------------------------------- + +// input +layout(location = 0) in vec3 inPos; + + +void +main() +{ + const mat4 tMVP = tGlobalInfo.tCameraViewProjection * tObjectInfo.tModel; + vec4 inPosition = vec4(inPos, 1.0); + vec3 inNormal = vec3(0.0, 0.0, 0.0); + + const uint iVertexDataOffset = iDataStride * (gl_VertexIndex - tObjectInfo.iVertexOffset) + tObjectInfo.iDataOffset; + int iCurrentAttribute = 0; + if(bool(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_POSITION)) iCurrentAttribute++; + if(bool(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_NORMAL)) { inNormal = tVertexBuffer.atVertexData[iVertexDataOffset + iCurrentAttribute].xyz;} + + vec4 tPos = tMVP * inPosition; + vec4 tNorm = normalize(tMVP * vec4(inNormal, 0.0)); + tPos = vec4(tPos.xyz + tNorm.xyz * tObjectInfo.fThickness, tPos.w); + gl_Position = tPos; +} \ No newline at end of file diff --git a/shaders/metal/outline.metal b/shaders/metal/outline.metal new file mode 100644 index 00000000..29cb7af5 --- /dev/null +++ b/shaders/metal/outline.metal @@ -0,0 +1,107 @@ +#include +#include + +using namespace metal; + +//----------------------------------------------------------------------------- +// [SECTION] specialization constants +//----------------------------------------------------------------------------- + +constant int iMeshVariantFlags [[ function_constant(0) ]]; +constant int iDataStride [[ function_constant(1) ]]; + +//----------------------------------------------------------------------------- +// [SECTION] defines & structs +//----------------------------------------------------------------------------- + +// iMeshVariantFlags +#define PL_MESH_FORMAT_FLAG_HAS_POSITION 1 << 0 +#define PL_MESH_FORMAT_FLAG_HAS_NORMAL 1 << 1 + +//----------------------------------------------------------------------------- +// [SECTION] bind group 0 +//----------------------------------------------------------------------------- + +struct BindGroupData_0 +{ + float4 tCameraPosition; + float4x4 tCameraView; + float4x4 tCameraProjection; + float4x4 tCameraViewProjection; +}; + +struct BindGroup_0 +{ + device BindGroupData_0 *data; + device float4 *atVertexData; +}; + +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +struct DynamicData +{ + float4 tColor; + float fThickness; + int iDataOffset; + int iVertexOffset; + int iPadding[1]; + float4x4 tModel; +}; + +//----------------------------------------------------------------------------- +// [SECTION] input +//----------------------------------------------------------------------------- + +struct VertexIn { + float3 tPosition [[attribute(0)]]; +}; + + +//----------------------------------------------------------------------------- +// [SECTION] entry +//----------------------------------------------------------------------------- + +struct VertexOut { + float4 tPositionOut [[position]]; +}; + +vertex VertexOut vertex_main( + uint vertexID [[ vertex_id ]], + VertexIn in [[stage_in]], + device const BindGroup_0& bg0 [[ buffer(1) ]], + device const DynamicData& tObjectInfo [[ buffer(2) ]] + ) +{ + + const float4x4 tMVP = bg0.data->tCameraViewProjection * tObjectInfo.tModel; + float4 inPosition = float4(in.tPosition, 1.0); + float3 inNormal = float3(0.0, 0.0, 0.0); + + int iCurrentAttribute = 0; + + const uint iVertexDataOffset = iDataStride * (vertexID - tObjectInfo.iVertexOffset) + tObjectInfo.iDataOffset; + + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_POSITION) { iCurrentAttribute++;} + if(iMeshVariantFlags & PL_MESH_FORMAT_FLAG_HAS_NORMAL) { inNormal = bg0.atVertexData[iVertexDataOffset + iCurrentAttribute].xyz; iCurrentAttribute++;} + + float4 tPos = tMVP * inPosition; + float4 tNorm = fast::normalize(tMVP * float4(inNormal, 0.0)); + tPos = float4(tPos.xyz + tNorm.xyz * tObjectInfo.fThickness, tPos.w); + + VertexOut tOut; + tOut.tPositionOut = tPos; + tOut.tPositionOut.y = tOut.tPositionOut.y * -1.0; + return tOut; +} + +fragment float4 fragment_main( + VertexOut in [[stage_in]], + device const BindGroup_0& bg0 [[ buffer(1) ]], + device const DynamicData& tObjectInfo [[ buffer(2) ]], + bool front_facing [[front_facing]] + ) +{ + return tObjectInfo.tColor; +} \ No newline at end of file