diff --git a/include/mbgl/shaders/layer_ubo.hpp b/include/mbgl/shaders/layer_ubo.hpp index a6d6a5a27..c9bb02036 100644 --- a/include/mbgl/shaders/layer_ubo.hpp +++ b/include/mbgl/shaders/layer_ubo.hpp @@ -71,14 +71,8 @@ enum { globalUBOCount }; -enum { - idDrawableReservedVertexOnlyUBO = globalUBOCount, - idDrawableReservedFragmentOnlyUBO, - drawableReservedUBOCount -}; - #define MLN_UBO_CONSOLIDATION (MLN_RENDER_BACKEND_METAL || MLN_RENDER_BACKEND_VULKAN || MLN_RENDER_BACKEND_WEBGPU) -#define MLN_USE_FILL_EXTRUSION_INSTANCING (MLN_RENDER_BACKEND_METAL) +#define MLN_USE_FILL_EXTRUSION_INSTANCING (MLN_RENDER_BACKEND_METAL || MLN_RENDER_BACKEND_VULKAN) } // namespace shaders } // namespace mbgl diff --git a/include/mbgl/shaders/shader_defines.hpp b/include/mbgl/shaders/shader_defines.hpp index 11e26d610..b51584a0d 100644 --- a/include/mbgl/shaders/shader_defines.hpp +++ b/include/mbgl/shaders/shader_defines.hpp @@ -7,253 +7,281 @@ namespace mbgl { namespace shaders { -// drawable UBOs - -enum { - idBackgroundDrawableUBO = idDrawableReservedVertexOnlyUBO, - backgroundDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idCircleDrawableUBO = idDrawableReservedVertexOnlyUBO, - circleDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idClippingMaskUBO = idDrawableReservedVertexOnlyUBO, - clippingMaskDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idCollisionDrawableUBO = idDrawableReservedVertexOnlyUBO, - idCollisionTilePropsUBO = drawableReservedUBOCount, - collisionDrawableUBOCount -}; - -enum { - idCustomGeometryDrawableUBO = drawableReservedUBOCount, - customGeometryDrawableUBOCount -}; - -enum { - idCustomSymbolDrawableUBO = idDrawableReservedVertexOnlyUBO, - customSymbolDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idDebugUBO = drawableReservedUBOCount, - debugDrawableUBOCount -}; - -enum { - idFillDrawableUBO = idDrawableReservedVertexOnlyUBO, - idFillTilePropsUBO = drawableReservedUBOCount, - fillDrawableUBOCount -}; - -enum { - idFillExtrusionDrawableUBO = idDrawableReservedVertexOnlyUBO, - idFillExtrusionTilePropsUBO = drawableReservedUBOCount, - fillExtrusionDrawableUBOCount -}; - -enum { - idHeatmapDrawableUBO = idDrawableReservedVertexOnlyUBO, - heatmapDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - heatmapTextureDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idHillshadeDrawableUBO = idDrawableReservedVertexOnlyUBO, - idHillshadeTilePropsUBO = idDrawableReservedFragmentOnlyUBO, - hillshadeDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idHillshadePrepareDrawableUBO = idDrawableReservedVertexOnlyUBO, - idHillshadePrepareTilePropsUBO = drawableReservedUBOCount, - hillshadePrepareDrawableUBOCount -}; - -enum { - idColorReliefDrawableUBO = idDrawableReservedVertexOnlyUBO, - idColorReliefTilePropsUBO = drawableReservedUBOCount, - colorReliefDrawableUBOCount -}; - -enum { - idLineDrawableUBO = idDrawableReservedVertexOnlyUBO, - idLineTilePropsUBO = idDrawableReservedFragmentOnlyUBO, - lineDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idLocationIndicatorDrawableUBO = drawableReservedUBOCount, - locationIndicatorDrawableUBOCount -}; - -enum { - idRasterDrawableUBO = idDrawableReservedVertexOnlyUBO, - rasterDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idSymbolDrawableUBO = idDrawableReservedVertexOnlyUBO, - idSymbolTilePropsUBO = idDrawableReservedFragmentOnlyUBO, - symbolDrawableUBOCount = drawableReservedUBOCount -}; - -enum { - idWideVectorUniformsUBO = idDrawableReservedVertexOnlyUBO, - idWideVectorUniformWideVecUBO = drawableReservedUBOCount, - wideVectorDrawableUBOCount -}; +// layer SSBOs static constexpr uint32_t layerSSBOStartId = globalUBOCount; -static constexpr uint32_t layerUBOStartId = std::max({static_cast(backgroundDrawableUBOCount), - static_cast(circleDrawableUBOCount), - static_cast(clippingMaskDrawableUBOCount), - static_cast(collisionDrawableUBOCount), - static_cast(customGeometryDrawableUBOCount), - static_cast(customSymbolDrawableUBOCount), - static_cast(debugDrawableUBOCount), - static_cast(fillDrawableUBOCount), - static_cast(fillExtrusionDrawableUBOCount), - static_cast(heatmapDrawableUBOCount), - static_cast(heatmapTextureDrawableUBOCount), - static_cast(hillshadeDrawableUBOCount), - static_cast(hillshadePrepareDrawableUBOCount), - static_cast(colorReliefDrawableUBOCount), - static_cast(lineDrawableUBOCount), - static_cast(locationIndicatorDrawableUBOCount), - static_cast(rasterDrawableUBOCount), - static_cast(symbolDrawableUBOCount), - static_cast(wideVectorDrawableUBOCount)}); -static constexpr uint32_t maxUBOCountPerDrawable = layerUBOStartId - globalUBOCount; +enum { + idDrawableReservedVertexOnlyUBO = layerSSBOStartId, + idDrawableReservedFragmentOnlyUBO, + drawableReservedUBOCount +}; + +enum { + idBackgroundDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + backgroundLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idCircleDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + circleLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idColorReliefDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idColorReliefTilePropsUBO = drawableReservedUBOCount, // SSBO + colorReliefLayerSSBOCount +}; + +enum { + idFillDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idFillTilePropsUBO = drawableReservedUBOCount, // SSBO + fillLayerSSBOCount +}; + +enum { + idFillExtrusionDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idFillExtrusionTilePropsUBO = drawableReservedUBOCount, // both SSBO and UBO? + fillExtrusionLayerSSBOCount +}; + +enum { + idHeatmapDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + heatmapLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idHillshadeDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idHillshadeTilePropsUBO = idDrawableReservedFragmentOnlyUBO, // SSBO + hillshadeLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idLineDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idLineTilePropsUBO = idDrawableReservedFragmentOnlyUBO, // SSBO + lineLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idRasterDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + rasterLayerSSBOCount = drawableReservedUBOCount +}; + +enum { + idSymbolDrawableUBO = idDrawableReservedVertexOnlyUBO, // SSBO + idSymbolTilePropsUBO = idDrawableReservedFragmentOnlyUBO, // SSBO + symbolLayerSSBOCount = drawableReservedUBOCount +}; // layer UBOs +static constexpr uint32_t layerUBOStartId = std::max({static_cast(drawableReservedUBOCount), + static_cast(backgroundLayerSSBOCount), + static_cast(circleLayerSSBOCount), + static_cast(fillLayerSSBOCount), + static_cast(fillExtrusionLayerSSBOCount), + static_cast(heatmapLayerSSBOCount), + static_cast(hillshadeLayerSSBOCount), + static_cast(colorReliefLayerSSBOCount), + static_cast(lineLayerSSBOCount), + static_cast(rasterLayerSSBOCount), + static_cast(symbolLayerSSBOCount)}); #if MLN_RENDER_BACKEND_VULKAN -#define getLayerStartValue(packedValue) layerUBOStartId +#define getEnumValue(packed, unpacked) unpacked #else -#define getLayerStartValue(packedValue) packedValue +#define getEnumValue(packed, unpacked) packed #endif enum { - idBackgroundPropsUBO = getLayerStartValue(backgroundDrawableUBOCount), - backgroundUBOCount + idBackgroundPropsUBO = getEnumValue(backgroundLayerSSBOCount, layerUBOStartId), + backgroundLayerUBOCount }; enum { - idCircleEvaluatedPropsUBO = getLayerStartValue(circleDrawableUBOCount), - circleUBOCount + idCircleEvaluatedPropsUBO = getEnumValue(circleLayerSSBOCount, layerUBOStartId), + circleLayerUBOCount }; enum { - clippingMaskUBOCount = getLayerStartValue(clippingMaskDrawableUBOCount) + idColorReliefEvaluatedPropsUBO = getEnumValue(colorReliefLayerSSBOCount, layerUBOStartId), + colorReliefLayerUBOCount }; enum { - collisionUBOCount = getLayerStartValue(collisionDrawableUBOCount) + idFillEvaluatedPropsUBO = getEnumValue(fillLayerSSBOCount, layerUBOStartId), + fillLayerUBOCount }; enum { - customGeometryUBOCount = getLayerStartValue(customGeometryDrawableUBOCount) + idFillExtrusionPropsUBO = getEnumValue(fillExtrusionLayerSSBOCount, layerUBOStartId), + fillExtrusionLayerUBOCount }; enum { - customSymbolUBOCount = getLayerStartValue(customSymbolDrawableUBOCount) + idHeatmapEvaluatedPropsUBO = getEnumValue(heatmapLayerSSBOCount, layerUBOStartId), + heatmapLayerUBOCount }; enum { - debugUBOCount = getLayerStartValue(debugDrawableUBOCount) -}; - -enum { - idFillEvaluatedPropsUBO = getLayerStartValue(fillDrawableUBOCount), - fillUBOCount -}; - -enum { - idFillExtrusionPropsUBO = getLayerStartValue(fillExtrusionDrawableUBOCount), - fillExtrusionUBOCount -}; - -enum { - idHeatmapEvaluatedPropsUBO = getLayerStartValue(heatmapDrawableUBOCount), - heatmapUBOCount -}; - -enum { - idHeatmapTexturePropsUBO = getLayerStartValue(heatmapTextureDrawableUBOCount), + idHeatmapTexturePropsUBO = getEnumValue(drawableReservedUBOCount, layerUBOStartId), heatmapTextureUBOCount }; enum { - idHillshadeEvaluatedPropsUBO = getLayerStartValue(hillshadeDrawableUBOCount), - hillshadeUBOCount + idHillshadeEvaluatedPropsUBO = getEnumValue(hillshadeLayerSSBOCount, layerUBOStartId), + hillshadeLayerUBOCount }; enum { - hillshadePrepareUBOCount = getLayerStartValue(hillshadePrepareDrawableUBOCount) -}; - -enum { - idColorReliefEvaluatedPropsUBO = getLayerStartValue(colorReliefDrawableUBOCount), - colorReliefUBOCount -}; - -enum { - idLineEvaluatedPropsUBO = getLayerStartValue(lineDrawableUBOCount), + idLineEvaluatedPropsUBO = getEnumValue(lineLayerSSBOCount, layerUBOStartId), idLineExpressionUBO, - lineUBOCount + lineLayerUBOCount }; enum { - locationIndicatorUBOCount = getLayerStartValue(locationIndicatorDrawableUBOCount) + idRasterEvaluatedPropsUBO = getEnumValue(rasterLayerSSBOCount, layerUBOStartId), + rasterLayerUBOCount }; enum { - idRasterEvaluatedPropsUBO = getLayerStartValue(rasterDrawableUBOCount), - rasterUBOCount + idSymbolEvaluatedPropsUBO = getEnumValue(symbolLayerSSBOCount, layerUBOStartId), + symbolLayerUBOCount +}; + +// drawable SSBOs + +static constexpr uint32_t drawableSSBOStartId = std::max({static_cast(backgroundLayerUBOCount), + static_cast(circleLayerUBOCount), + static_cast(colorReliefLayerUBOCount), + static_cast(fillLayerUBOCount), + static_cast(fillExtrusionLayerUBOCount), + static_cast(heatmapLayerUBOCount), + static_cast(hillshadeLayerUBOCount), + static_cast(lineLayerUBOCount), + static_cast(rasterLayerUBOCount), + static_cast(symbolLayerUBOCount)}); + +enum { +#if MLN_USE_FILL_EXTRUSION_INSTANCING + idFillExtrusionInstanced = getEnumValue(fillExtrusionLayerUBOCount, drawableSSBOStartId), +#endif + fillExtrusionDrawableSSBOCount +}; + +// drawable UBOs + +static constexpr uint32_t drawableUBOStartId = std::max( + {static_cast(drawableSSBOStartId), static_cast(fillExtrusionDrawableSSBOCount)}); + +enum { + backgroundUBOCount = getEnumValue(backgroundLayerUBOCount, drawableUBOStartId) }; enum { - idSymbolEvaluatedPropsUBO = getLayerStartValue(symbolDrawableUBOCount), - symbolUBOCount + circleUBOCount = getEnumValue(circleLayerUBOCount, drawableUBOStartId) }; enum { - wideVectorUBOCount = getLayerStartValue(wideVectorDrawableUBOCount) + idCollisionDrawableUBO = getEnumValue(idDrawableReservedVertexOnlyUBO, drawableUBOStartId), // UBO + idCollisionTilePropsUBO = getEnumValue(drawableReservedUBOCount, idCollisionDrawableUBO + 1), + collisionUBOCount }; -#undef getLayerStartValue +enum { + idClippingMaskUBO = getEnumValue(idDrawableReservedVertexOnlyUBO, drawableUBOStartId), + clippingMaskUBOCount = getEnumValue(drawableReservedUBOCount, idClippingMaskUBO + 1) +}; + +enum { + colorReliefUBOCount = getEnumValue(colorReliefLayerUBOCount, drawableUBOStartId) +}; + +enum { + idCustomGeometryDrawableUBO = getEnumValue(drawableReservedUBOCount, drawableUBOStartId), // UBO + customGeometryUBOCount +}; + +enum { + idCustomSymbolDrawableUBO = getEnumValue(idDrawableReservedVertexOnlyUBO, drawableUBOStartId), // UBO + customSymbolUBOCount = getEnumValue(drawableReservedUBOCount, idCustomSymbolDrawableUBO + 1) +}; + +enum { + idDebugUBO = getEnumValue(drawableReservedUBOCount, drawableUBOStartId), // UBO + debugUBOCount +}; + +enum { + fillUBOCount = getEnumValue(fillLayerUBOCount, drawableUBOStartId) +}; + +enum { + fillExtrusionUBOCount = getEnumValue(fillExtrusionLayerUBOCount, drawableUBOStartId) +}; + +enum { + heatmapUBOCount = getEnumValue(heatmapLayerUBOCount, drawableUBOStartId) +}; + +enum { + idHillshadePrepareDrawableUBO = getEnumValue(idDrawableReservedVertexOnlyUBO, drawableUBOStartId), // UBO + idHillshadePrepareTilePropsUBO = getEnumValue(drawableReservedUBOCount, idHillshadePrepareDrawableUBO + 1), // UBO + hillshadePrepareUBOCount +}; + +enum { + hillshadeUBOCount = getEnumValue(hillshadeLayerUBOCount, drawableUBOStartId) +}; + +enum { + lineUBOCount = getEnumValue(lineLayerUBOCount, drawableUBOStartId) +}; + +enum { + idLocationIndicatorDrawableUBO = getEnumValue(drawableReservedUBOCount, drawableUBOStartId), // UBO + locationIndicatorUBOCount +}; + +enum { + rasterUBOCount = getEnumValue(rasterLayerUBOCount, drawableUBOStartId) +}; + +enum { + symbolUBOCount = getEnumValue(symbolLayerUBOCount, drawableUBOStartId) +}; + +enum { + idWideVectorUniformsUBO = getEnumValue(idDrawableReservedVertexOnlyUBO, drawableUBOStartId), // UBO + idWideVectorUniformWideVecUBO = getEnumValue(drawableReservedUBOCount, idWideVectorUniformsUBO + 1), // UBO + wideVectorUBOCount +}; + +#undef getEnumValue static constexpr uint32_t maxUBOCountPerShader = std::max({static_cast(backgroundUBOCount), static_cast(circleUBOCount), static_cast(clippingMaskUBOCount), static_cast(collisionUBOCount), - static_cast(customSymbolUBOCount), + static_cast(colorReliefUBOCount), + static_cast(customGeometryUBOCount), static_cast(debugUBOCount), static_cast(fillUBOCount), static_cast(fillExtrusionUBOCount), - static_cast(heatmapUBOCount), static_cast(heatmapTextureUBOCount), - static_cast(hillshadeUBOCount), + static_cast(heatmapUBOCount), static_cast(hillshadePrepareUBOCount), - static_cast(colorReliefUBOCount), + static_cast(hillshadeUBOCount), static_cast(lineUBOCount), static_cast(locationIndicatorUBOCount), static_cast(rasterUBOCount), static_cast(symbolUBOCount), static_cast(wideVectorUBOCount)}); -static constexpr uint32_t maxSSBOCountPerLayer = maxUBOCountPerDrawable; -static constexpr uint32_t maxUBOCountPerLayer = maxUBOCountPerShader - layerUBOStartId; +static constexpr uint32_t maxSSBOCountPerLayer = layerUBOStartId - layerSSBOStartId; +static constexpr uint32_t maxUBOCountPerLayer = drawableSSBOStartId - layerUBOStartId; + +static constexpr uint32_t maxSSBOCountPerDrawable = drawableUBOStartId - drawableSSBOStartId; +static constexpr uint32_t maxUBOCountPerDrawable = maxUBOCountPerShader - drawableUBOStartId; // Texture defines enum { diff --git a/include/mbgl/shaders/vulkan/collision.hpp b/include/mbgl/shaders/vulkan/collision.hpp index aece0c81d..7455d1876 100644 --- a/include/mbgl/shaders/vulkan/collision.hpp +++ b/include/mbgl/shaders/vulkan/collision.hpp @@ -8,8 +8,8 @@ namespace shaders { constexpr auto collisionShaderPrelude = R"( -#define idCollisionDrawableUBO idDrawableReservedVertexOnlyUBO -#define idCollisionTilePropsUBO drawableReservedUBOCount +#define idCollisionDrawableUBO drawableUBOStartId +#define idCollisionTilePropsUBO drawableUBOStartId + 1 )"; diff --git a/include/mbgl/shaders/vulkan/common.hpp b/include/mbgl/shaders/vulkan/common.hpp index 8d3af26b9..4a33aa5de 100644 --- a/include/mbgl/shaders/vulkan/common.hpp +++ b/include/mbgl/shaders/vulkan/common.hpp @@ -67,15 +67,33 @@ vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, return (tile_units_to_pixels * pos + offset) / pattern_size; } -#define GLOBAL_SET_INDEX 0 -#define LAYER_SET_INDEX 1 -#define DRAWABLE_UBO_SET_INDEX 2 -#define DRAWABLE_IMAGE_SET_INDEX 3 +vec2 unpack_int(int value) { + const int low = (value << 16) >> 16; + const int high = value >> 16; -#define idDrawableReservedVertexOnlyUBO 0 -#define idDrawableReservedFragmentOnlyUBO 1 -#define drawableReservedUBOCount 2 -#define layerUBOStartId 3 + return vec2(low, high); +} + +vec2 unpack_uint(uint value) { + const uint low = value & 0xFFFF; + const uint high = (value >> 16) & 0xFFFF; + + return vec2(low, high); +} + +#define GLOBAL_SET_INDEX 0 +#define LAYER_SET_INDEX 1 +#define DRAWABLE_UBO_SET_INDEX 2 +#define DRAWABLE_IMAGE_SET_INDEX 3 + +#define layerSSBOStartId 0 +#define layerUBOStartId 3 +#define drawableSSBOStartId 0 +#define drawableUBOStartId 1 + +#define idDrawableReservedVertexOnlyUBO layerSSBOStartId +#define idDrawableReservedFragmentOnlyUBO idDrawableReservedVertexOnlyUBO + 1 +#define drawableReservedUBOCount idDrawableReservedFragmentOnlyUBO + 1 layout(set = GLOBAL_SET_INDEX, binding = 0) uniform GlobalPaintParamsUBO { vec2 pattern_atlas_texsize; @@ -110,15 +128,19 @@ void applySurfaceTransform() { #define M_PI 3.1415926535897932384626433832795 #define SDF_PX 8.0 -#define GLOBAL_SET_INDEX 0 -#define LAYER_SET_INDEX 1 -#define DRAWABLE_UBO_SET_INDEX 2 -#define DRAWABLE_IMAGE_SET_INDEX 3 +#define GLOBAL_SET_INDEX 0 +#define LAYER_SET_INDEX 1 +#define DRAWABLE_UBO_SET_INDEX 2 +#define DRAWABLE_IMAGE_SET_INDEX 3 -#define idDrawableReservedVertexOnlyUBO 0 -#define idDrawableReservedFragmentOnlyUBO 1 -#define drawableReservedUBOCount 2 -#define layerUBOStartId 3 +#define layerSSBOStartId 0 +#define layerUBOStartId 3 +#define drawableSSBOStartId 0 +#define drawableUBOStartId 1 + +#define idDrawableReservedVertexOnlyUBO layerSSBOStartId +#define idDrawableReservedFragmentOnlyUBO idDrawableReservedVertexOnlyUBO + 1 +#define drawableReservedUBOCount idDrawableReservedFragmentOnlyUBO + 1 layout(set = GLOBAL_SET_INDEX, binding = 0) uniform GlobalPaintParamsUBO { vec2 pattern_atlas_texsize; diff --git a/include/mbgl/shaders/vulkan/custom_geometry.hpp b/include/mbgl/shaders/vulkan/custom_geometry.hpp index 17cc135b0..c08dd782c 100644 --- a/include/mbgl/shaders/vulkan/custom_geometry.hpp +++ b/include/mbgl/shaders/vulkan/custom_geometry.hpp @@ -6,7 +6,7 @@ namespace mbgl { namespace shaders { -constexpr auto customGeometryShaderPrelude = R"(#define idCustomGeometryDrawableUBO drawableReservedUBOCount)"; +constexpr auto customGeometryShaderPrelude = R"(#define idCustomGeometryDrawableUBO drawableUBOStartId)"; template <> struct ShaderSource { diff --git a/include/mbgl/shaders/vulkan/custom_symbol_icon.hpp b/include/mbgl/shaders/vulkan/custom_symbol_icon.hpp index 69a4fb933..ad7df8fb7 100644 --- a/include/mbgl/shaders/vulkan/custom_symbol_icon.hpp +++ b/include/mbgl/shaders/vulkan/custom_symbol_icon.hpp @@ -6,7 +6,7 @@ namespace mbgl { namespace shaders { -constexpr auto customSymbolIconShaderPrelude = R"(#define idCustomSymbolDrawableUBO idDrawableReservedVertexOnlyUBO)"; +constexpr auto customSymbolIconShaderPrelude = R"(#define idCustomSymbolDrawableUBO drawableUBOStartId)"; template <> struct ShaderSource { diff --git a/include/mbgl/shaders/vulkan/debug.hpp b/include/mbgl/shaders/vulkan/debug.hpp index 0725a0524..fc4020ecb 100644 --- a/include/mbgl/shaders/vulkan/debug.hpp +++ b/include/mbgl/shaders/vulkan/debug.hpp @@ -6,7 +6,7 @@ namespace mbgl { namespace shaders { -constexpr auto debugShaderPrelude = R"(#define idDebugUBO drawableReservedUBOCount)"; +constexpr auto debugShaderPrelude = R"(#define idDebugUBO drawableUBOStartId)"; template <> struct ShaderSource { diff --git a/include/mbgl/shaders/vulkan/fill_extrusion.hpp b/include/mbgl/shaders/vulkan/fill_extrusion.hpp index 8a04b99aa..77594ad28 100644 --- a/include/mbgl/shaders/vulkan/fill_extrusion.hpp +++ b/include/mbgl/shaders/vulkan/fill_extrusion.hpp @@ -8,9 +8,10 @@ namespace shaders { constexpr auto fillExtrusionShaderPrelude = R"( -#define idFillExtrusionDrawableUBO idDrawableReservedVertexOnlyUBO -#define idFillExtrusionTilePropsUBO drawableReservedUBOCount -#define idFillExtrusionPropsUBO layerUBOStartId +#define idFillExtrusionDrawableUBO idDrawableReservedVertexOnlyUBO +#define idFillExtrusionTilePropsUBO drawableReservedUBOCount +#define idFillExtrusionPropsUBO layerUBOStartId +#define idFillExtrusionInstancedDrawableUBO drawableSSBOStartId )"; @@ -18,7 +19,7 @@ template <> struct ShaderSource { static constexpr const char* name = "FillExtrusionShader"; - static const std::array attributes; + static const std::array attributes; static constexpr std::array instanceAttributes{}; static const std::array textures; @@ -26,18 +27,17 @@ struct ShaderSource { static constexpr auto vertex = R"( layout(location = 0) in ivec2 in_position; -layout(location = 1) in ivec4 in_normal_ed; #if !defined(HAS_UNIFORM_u_color) -layout(location = 2) in vec4 in_color; +layout(location = 1) in vec4 in_color; #endif #if !defined(HAS_UNIFORM_u_base) -layout(location = 3) in vec2 in_base; +layout(location = 2) in vec2 in_base; #endif #if !defined(HAS_UNIFORM_u_height) -layout(location = 4) in vec2 in_height; +layout(location = 3) in vec2 in_height; #endif layout(push_constant) uniform Constants { @@ -100,8 +100,8 @@ void main() { vec4 color = unpack_mix_color(in_color, drawable.color_t); #endif - const vec3 normal = in_normal_ed.xyz; - const float t = mod(normal.x, 2.0); + const vec3 normal = vec3(0.0, 0.0, 1.0); + const float t = 1.0; const float z = t != 0.0 ? height : base; gl_Position = drawable.matrix * vec4(in_position, z, 1.0); @@ -121,7 +121,177 @@ void main() { color += vec4(0.03, 0.03, 0.03, 1.0); // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray - const float directionalFraction = clamp(dot(normal / 16384.0, props.light_position_base.xyz), 0.0, 1.0); + const float directionalFraction = clamp(dot(normal, props.light_position_base.xyz), 0.0, 1.0); + + // Adjust directional so that the range of values for highlight/shading is + // narrower with lower light intensity and with lighter/brighter surface colors + const float minDirectional = 1.0 - props.light_intensity; + const float maxDirectional = max(1.0 - luminance + props.light_intensity, 1.0); + float directional = mix(minDirectional, maxDirectional, directionalFraction); + + // Add gradient along z axis of side surfaces + if (normal.y != 0.0) { + // This avoids another branching statement, but multiplies by a constant of 0.84 if no + // vertical gradient, and otherwise calculates the gradient based on base + height + // TODO: If we're optimizing to the level of avoiding branches, we should pre-compute + // the square root when height is a uniform. + const float fMin = mix(0.7, 0.98, 1.0 - props.light_intensity); + const float factor = clamp((t + base) * pow(height / 150.0, 0.5), fMin, 1.0); + directional *= (1.0 - props.vertical_gradient) + (props.vertical_gradient * factor); + } + + // Assign final color based on surface + ambient light color, diffuse light directional, + // and light color with lower bounds adjusted to hue of light so that shading is tinted + // with the complementary (opposite) color to the light color + const vec3 light_color = props.light_color_pad.rgb; + const vec3 minLight = mix(vec3(0.0), vec3(0.3), 1.0 - light_color.rgb); + vcolor += vec4(clamp(color.rgb * directional * light_color.rgb, minLight, vec3(1.0)), 0.0); + + frag_color = vcolor * props.opacity; +} +)"; + static constexpr auto fragment = R"( + +layout(location = 0) in vec4 frag_color; +layout(location = 0) out vec4 out_color; + +void main() { + out_color = frag_color; +} +)"; +}; + +template <> +struct ShaderSource { + static constexpr const char* name = "FillExtrusionInstancedShader"; + + static const std::array attributes; + static const std::array instanceAttributes; + static const std::array textures; + + static constexpr auto prelude = fillExtrusionShaderPrelude; + + static constexpr auto vertex = R"( + +layout(location = 0) in ivec2 in_position; + +#if !defined(HAS_UNIFORM_u_color) +layout(location = 3) in vec4 in_color; +#endif + +#if !defined(HAS_UNIFORM_u_base) +layout(location = 4) in vec2 in_base; +#endif + +#if !defined(HAS_UNIFORM_u_height) +layout(location = 5) in vec2 in_height; +#endif + +layout(push_constant) uniform Constants { + int ubo_index; +} constant; + +struct FillExtrusionDrawableUBO { + mat4 matrix; + vec2 pixel_coord_upper; + vec2 pixel_coord_lower; + float height_factor; + float tile_ratio; + // Interpolations + float base_t; + float height_t; + float color_t; + float pattern_from_t; + float pattern_to_t; + float pad1; +}; + +layout(std140, set = LAYER_SET_INDEX, binding = idFillExtrusionDrawableUBO) readonly buffer FillExtrusionDrawableUBOVector { + FillExtrusionDrawableUBO drawable_ubo[]; +} drawableVector; + +layout(set = LAYER_SET_INDEX, binding = idFillExtrusionPropsUBO) uniform FillExtrusionPropsUBO { + vec4 color; + vec4 light_color_pad; + vec4 light_position_base; + float height; + float light_intensity; + float vertical_gradient; + float opacity; + float fade; + float from_scale; + float to_scale; + float pad2; +} props; + +struct OutlineInstance { + int pos; + uint ed_discard; +}; + +layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idFillExtrusionInstancedDrawableUBO) readonly buffer FillExtrusionInstanceVector { + OutlineInstance instance[]; +} instanceVector; + +layout(location = 0) out mediump vec4 frag_color; + +void main() { + + const vec2 instancePos = unpack_int(instanceVector.instance[gl_InstanceIndex].pos); + const vec2 instanceEd = unpack_uint(instanceVector.instance[gl_InstanceIndex].ed_discard); + + if (instanceEd.y > 0.0) { + gl_Position = vec4(0.0); + frag_color = vec4(0.0); + return; + } + + const FillExtrusionDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index]; + +#if defined(HAS_UNIFORM_u_base) + const float base = props.light_position_base.w; +#else + const float base = max(unpack_mix_float(in_base, drawable.base_t), 0.0); +#endif + +#if defined(HAS_UNIFORM_u_height) + const float height = props.height; +#else + const float height = max(unpack_mix_float(in_height, drawable.height_t), 0.0); +#endif + +#if defined(HAS_UNIFORM_u_color) + vec4 color = props.color; +#else + vec4 color = unpack_mix_color(in_color, drawable.color_t); +#endif + + const vec2 p1 = unpack_int(instanceVector.instance[gl_InstanceIndex + 1].pos); + const vec2 p2 = unpack_int(instanceVector.instance[gl_InstanceIndex + 0].pos); + const vec2 perp = normalize(p1 - p2); + + const vec3 normal = vec3(-perp.y, perp.x, 0.0); + const float t = float(in_position.y); + const float z = t != 0.0 ? height : base; + + gl_Position = drawable.matrix * vec4(unpack_int(instanceVector.instance[gl_InstanceIndex + in_position.x].pos), z, 1.0); + applySurfaceTransform(); + +#if defined(OVERDRAW_INSPECTOR) + frag_color = vec4(1.0); + return; +#endif + + // Relative luminance (how dark/bright is the surface color?) + const float luminance = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; + + vec4 vcolor = vec4(0.0, 0.0, 0.0, 1.0); + + // Add slight ambient lighting so no extrusions are totally black + color += vec4(0.03, 0.03, 0.03, 1.0); + + // Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray + const float directionalFraction = clamp(dot(normal, props.light_position_base.xyz), 0.0, 1.0); // Adjust directional so that the range of values for highlight/shading is // narrower with lower light intensity and with lighter/brighter surface colors @@ -166,7 +336,7 @@ template <> struct ShaderSource { static constexpr const char* name = "FillExtrusionPatternShader"; - static const std::array attributes; + static const std::array attributes; static constexpr std::array instanceAttributes{}; static const std::array textures; @@ -174,22 +344,21 @@ struct ShaderSource +struct ShaderSource { + static constexpr const char* name = "FillExtrusionPatternInstancedShader"; + + static const std::array attributes; + static const std::array instanceAttributes; + static const std::array textures; + + static constexpr auto prelude = fillExtrusionShaderPrelude; + static constexpr auto vertex = R"( + +layout(location = 0) in ivec2 in_position; + +#if !defined(HAS_UNIFORM_u_base) +layout(location = 3) in vec2 in_base; +#endif + +#if !defined(HAS_UNIFORM_u_height) +layout(location = 4) in vec2 in_height; +#endif + +#if !defined(HAS_UNIFORM_u_pattern_from) +layout(location = 5) in uvec4 in_pattern_from; +#endif + +#if !defined(HAS_UNIFORM_u_pattern_to) +layout(location = 6) in uvec4 in_pattern_to; +#endif + +layout(push_constant) uniform Constants { + int ubo_index; +} constant; + +struct FillExtrusionDrawableUBO { + mat4 matrix; + vec2 pixel_coord_upper; + vec2 pixel_coord_lower; + float height_factor; + float tile_ratio; + // Interpolations + float base_t; + float height_t; + float color_t; + float pattern_from_t; + float pattern_to_t; + float pad1; +}; + +layout(std140, set = LAYER_SET_INDEX, binding = idFillExtrusionDrawableUBO) readonly buffer FillExtrusionDrawableUBOVector { + FillExtrusionDrawableUBO drawable_ubo[]; +} drawableVector; + +struct OutlineInstance { + int pos; + uint ed_discard; +}; + +layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idFillExtrusionInstancedDrawableUBO) readonly buffer FillExtrusionInstanceVector { + OutlineInstance instance[]; +} instanceVector; + +struct FillExtrusionTilePropsUBO { + vec4 pattern_from; + vec4 pattern_to; + vec2 texsize; + float pad1; + float pad2; +}; + +layout(std140, set = LAYER_SET_INDEX, binding = idFillExtrusionTilePropsUBO) readonly buffer FillExtrusionTilePropsUBOVector { + FillExtrusionTilePropsUBO tile_props_ubo[]; +} tilePropsVector; + +layout(set = LAYER_SET_INDEX, binding = idFillExtrusionPropsUBO) uniform FillExtrusionPropsUBO { + vec4 color; + vec4 light_color_pad; + vec4 light_position_base; + float height; + float light_intensity; + float vertical_gradient; + float opacity; + float fade; + float from_scale; + float to_scale; + float pad2; +} props; + +layout(location = 0) out mediump vec4 frag_lighting; +layout(location = 1) out mediump vec2 frag_pos_a; +layout(location = 2) out mediump vec2 frag_pos_b; + +#if !defined(HAS_UNIFORM_u_pattern_from) +layout(location = 3) out mediump vec4 frag_pattern_from; +#endif + +#if !defined(HAS_UNIFORM_u_pattern_to) +layout(location = 4) out mediump vec4 frag_pattern_to; +#endif + +void main() { + const vec2 instancePos = unpack_int(instanceVector.instance[gl_InstanceIndex].pos); + const vec2 instanceEd = unpack_uint(instanceVector.instance[gl_InstanceIndex].ed_discard); + + if (instanceEd.y > 0.0) { + gl_Position = vec4(0.0); + return; + } + + const FillExtrusionDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index]; + const FillExtrusionTilePropsUBO tileProps = tilePropsVector.tile_props_ubo[constant.ubo_index]; + +#if defined(HAS_UNIFORM_u_base) + const float base = props.light_position_base.w; +#else + const float base = max(unpack_mix_float(in_base, drawable.base_t), 0.0); +#endif + +#if defined(HAS_UNIFORM_u_height) + const float height = props.height; +#else + const float height = max(unpack_mix_float(in_height, drawable.height_t), 0.0); +#endif + + const vec2 p1 = unpack_int(instanceVector.instance[gl_InstanceIndex + 1].pos); + const vec2 p2 = unpack_int(instanceVector.instance[gl_InstanceIndex + 0].pos); + const vec2 perp = normalize(p1 - p2); + + const vec3 normal = vec3(-perp.y, perp.x, 0.0); + const float edgedistance = unpack_uint(instanceVector.instance[gl_InstanceIndex + 1 - in_position.x].ed_discard).x; + const float t = float(in_position.y); + const float z = t != 0.0 ? height : base; + + gl_Position = drawable.matrix * vec4(unpack_int(instanceVector.instance[gl_InstanceIndex + in_position.x].pos), z, 1.0); + applySurfaceTransform(); + +#if defined(OVERDRAW_INSPECTOR) + frag_lighting = vec4(1.0); + frag_pos_a = vec4(0.0); + frag_pos_b = vec4(0.0); + frag_pattern_from = vec4(0.0); + frag_pattern_to = vec4(0.0); + return; +#endif + +#if defined(HAS_UNIFORM_u_pattern_from) + const mediump vec4 pattern_from = tileProps.pattern_from; +#else + const mediump vec4 pattern_from = in_pattern_from; + frag_pattern_from = in_pattern_from; +#endif + +#if defined(HAS_UNIFORM_u_pattern_to) + const mediump vec4 pattern_to = tileProps.pattern_to; +#else + const mediump vec4 pattern_to = in_pattern_to; + frag_pattern_to = in_pattern_to; +#endif + + const vec2 pattern_tl_a = pattern_from.xy; + const vec2 pattern_br_a = pattern_from.zw; + const vec2 pattern_tl_b = pattern_to.xy; + const vec2 pattern_br_b = pattern_to.zw; + + const float pixelRatio = paintParams.pixel_ratio; + const float tileZoomRatio = drawable.tile_ratio; + const float fromScale = props.from_scale; + const float toScale = props.to_scale; + + const vec2 display_size_a = vec2((pattern_br_a.x - pattern_tl_a.x) / pixelRatio, (pattern_br_a.y - pattern_tl_a.y) / pixelRatio); + const vec2 display_size_b = vec2((pattern_br_b.x - pattern_tl_b.x) / pixelRatio, (pattern_br_b.y - pattern_tl_b.y) / pixelRatio); + + const vec2 pos = vec2(edgedistance, z * drawable.height_factor); // extrusion side + + vec4 lighting = vec4(0.0, 0.0, 0.0, 1.0); + float directional = clamp(dot(normal, props.light_position_base.xyz), 0.0, 1.0); directional = mix((1.0 - props.light_intensity), max((0.5 + props.light_intensity), 1.0), directional); if (normal.y != 0.0) { diff --git a/include/mbgl/shaders/vulkan/hillshade_prepare.hpp b/include/mbgl/shaders/vulkan/hillshade_prepare.hpp index 59218bd2b..23208ebd0 100644 --- a/include/mbgl/shaders/vulkan/hillshade_prepare.hpp +++ b/include/mbgl/shaders/vulkan/hillshade_prepare.hpp @@ -8,8 +8,8 @@ namespace shaders { constexpr auto hillshadePrepareShaderPrelude = R"( -#define idHillshadePrepareDrawableUBO idDrawableReservedVertexOnlyUBO -#define idHillshadePrepareTilePropsUBO drawableReservedUBOCount +#define idHillshadePrepareDrawableUBO drawableUBOStartId +#define idHillshadePrepareTilePropsUBO drawableUBOStartId + 1 )"; diff --git a/include/mbgl/shaders/vulkan/location_indicator.hpp b/include/mbgl/shaders/vulkan/location_indicator.hpp index f1f306737..0376bd785 100644 --- a/include/mbgl/shaders/vulkan/location_indicator.hpp +++ b/include/mbgl/shaders/vulkan/location_indicator.hpp @@ -6,7 +6,7 @@ namespace mbgl { namespace shaders { -constexpr auto locationIndicatorShaderPrelude = R"(#define idLocationIndicatorDrawableUBO drawableReservedUBOCount)"; +constexpr auto locationIndicatorShaderPrelude = R"(#define idLocationIndicatorDrawableUBO drawableUBOStartId)"; template <> struct ShaderSource { diff --git a/include/mbgl/shaders/vulkan/shader_group.hpp b/include/mbgl/shaders/vulkan/shader_group.hpp index 64e32cbc9..550e6f5cd 100644 --- a/include/mbgl/shaders/vulkan/shader_group.hpp +++ b/include/mbgl/shaders/vulkan/shader_group.hpp @@ -77,11 +77,13 @@ public: using ShaderClass = shaders::ShaderSource; for (const auto& attrib : ShaderClass::attributes) { if (!propertiesAsUniforms.second.contains(attrib.id)) { - shader->initAttribute(attrib); + shader->initVertexAttribute(attrib); } } for (const auto& attrib : ShaderClass::instanceAttributes) { - shader->initInstanceAttribute(attrib); + if (!propertiesAsUniforms.second.contains(attrib.id)) { + shader->initInstanceAttribute(attrib); + } } for (const auto& texture : ShaderClass::textures) { shader->initTexture(texture); diff --git a/include/mbgl/shaders/vulkan/shader_program.hpp b/include/mbgl/shaders/vulkan/shader_program.hpp index e07d52ce8..a439401e4 100644 --- a/include/mbgl/shaders/vulkan/shader_program.hpp +++ b/include/mbgl/shaders/vulkan/shader_program.hpp @@ -11,27 +11,17 @@ namespace mbgl { namespace shaders { -struct UniformBlockInfo { - constexpr UniformBlockInfo(bool vertex_, bool fragment_, std::size_t size_, std::size_t id_) - : index(id_), - vertex(vertex_), - fragment(fragment_), - size(size_), - id(id_) {} - std::size_t index; - bool vertex; - bool fragment; - std::size_t size; - std::size_t id; -}; + struct AttributeInfo { - constexpr AttributeInfo(std::size_t index_, gfx::AttributeDataType dataType_, std::size_t id_) + constexpr AttributeInfo(std::size_t index_, gfx::AttributeDataType dataType_, std::size_t id_, int ubo_ = -1) : index(index_), dataType(dataType_), - id(id_) {} + id(id_), + ubo(ubo_) {} std::size_t index; gfx::AttributeDataType dataType; std::size_t id; + int ubo; }; struct TextureInfo { constexpr TextureInfo(std::size_t index_, std::size_t id_) @@ -72,7 +62,7 @@ public: bool hasTextures() const; - void initAttribute(const shaders::AttributeInfo&); + void initVertexAttribute(const shaders::AttributeInfo&); void initInstanceAttribute(const shaders::AttributeInfo&); void initTexture(const shaders::TextureInfo&); diff --git a/include/mbgl/shaders/vulkan/widevector.hpp b/include/mbgl/shaders/vulkan/widevector.hpp index b0e34b759..f5dca1301 100644 --- a/include/mbgl/shaders/vulkan/widevector.hpp +++ b/include/mbgl/shaders/vulkan/widevector.hpp @@ -8,8 +8,8 @@ namespace shaders { constexpr auto wideVectorShaderPrelude = R"( -#define idWideVectorUniformsUBO idDrawableReservedVertexOnlyUBO -#define idWideVectorUniformWideVecUBO drawableReservedUBOCount +#define idWideVectorUniformsUBO drawableUBOStartId +#define idWideVectorUniformWideVecUBO drawableUBOStartId + 1 )"; diff --git a/include/mbgl/vulkan/buffer_resource.hpp b/include/mbgl/vulkan/buffer_resource.hpp index e93b8944a..b4860307e 100644 --- a/include/mbgl/vulkan/buffer_resource.hpp +++ b/include/mbgl/vulkan/buffer_resource.hpp @@ -47,6 +47,7 @@ public: BufferResource& operator=(BufferResource&&) noexcept; BufferResource clone() const; + BufferResource shared() const; void destroy(bool deferred = true); void update(const void* data, std::size_t size, std::size_t offset) noexcept; @@ -72,6 +73,9 @@ public: /// Used to detect whether buffer contents have changed VersionType getVersion() const noexcept { return version; } +protected: + BufferResource(const BufferResource&) noexcept; + protected: Context& context; std::size_t size; diff --git a/include/mbgl/vulkan/drawable.hpp b/include/mbgl/vulkan/drawable.hpp index df2cebe7c..5dc83a56b 100644 --- a/include/mbgl/vulkan/drawable.hpp +++ b/include/mbgl/vulkan/drawable.hpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -52,6 +53,7 @@ public: std::size_t segmentCount) override; protected: + void setSharedBuffers(const gfx::VertexAttributeArray&, const gfx::AttributeBindingArray&); void buildVulkanInputBindings(); bool bindAttributes(CommandEncoder&) const; diff --git a/include/mbgl/vulkan/upload_pass.hpp b/include/mbgl/vulkan/upload_pass.hpp index 45713e706..18f52b400 100644 --- a/include/mbgl/vulkan/upload_pass.hpp +++ b/include/mbgl/vulkan/upload_pass.hpp @@ -50,9 +50,9 @@ public: bool persistent) override; void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override; - const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, - gfx::BufferUsageType, - bool forceUpdate); + BufferResource createBufferResource(const void* data, std::size_t size, size_t usage, bool persistent); + + const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&, size_t usage, bool forceUpdate); gfx::AttributeBindingArray buildAttributeBindings( const std::size_t vertexCount, diff --git a/include/mbgl/vulkan/vertex_attribute.hpp b/include/mbgl/vulkan/vertex_attribute.hpp index b1ecb4ab8..699603991 100644 --- a/include/mbgl/vulkan/vertex_attribute.hpp +++ b/include/mbgl/vulkan/vertex_attribute.hpp @@ -21,10 +21,18 @@ public: VertexAttribute(const VertexAttribute& other) = delete; ~VertexAttribute() override = default; + void setUBO(int value) { ubo = value; } + int getUBO() const { return ubo; } + + size_t getBufferUsage() const; + static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&, UploadPass&, - const gfx::BufferUsageType, + size_t, bool forceUpdate); + +protected: + int ubo = -1; }; /// Stores a collection of vertex attributes by name diff --git a/src/mbgl/shaders/vulkan/fill_extrusion.cpp b/src/mbgl/shaders/vulkan/fill_extrusion.cpp index e7f600e2b..b9f6836e4 100644 --- a/src/mbgl/shaders/vulkan/fill_extrusion.cpp +++ b/src/mbgl/shaders/vulkan/fill_extrusion.cpp @@ -5,36 +5,79 @@ namespace mbgl { namespace shaders { +// idFillExtrusionInstanced is shared between instanced and non-instanced drawables + // // Fill extrusion using FillExtrusionShaderSource = ShaderSource; -const std::array FillExtrusionShaderSource::attributes = { - AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, - AttributeInfo{1, gfx::AttributeDataType::Short4, idFillExtrusionNormalEdVertexAttribute}, - AttributeInfo{2, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute}, - AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, - AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, +const std::array FillExtrusionShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced}, + AttributeInfo{1, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute}, + AttributeInfo{2, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, + AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, }; const std::array FillExtrusionShaderSource::textures = {}; +// +// Fill extrusion instanced + +using FillExtrusionInstancedShaderSource = + ShaderSource; + +const std::array FillExtrusionInstancedShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, +}; +const std::array FillExtrusionInstancedShaderSource::instanceAttributes = { + AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced}, + AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionEdDiscardAttribute, idFillExtrusionInstanced}, + + // Data driven + AttributeInfo{3, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute}, + AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, + AttributeInfo{5, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, +}; +const std::array FillExtrusionInstancedShaderSource::textures = {}; + // // Fill extrusion pattern using FillExtrusionPatternShaderSource = ShaderSource; -const std::array FillExtrusionPatternShaderSource::attributes = { - AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, - AttributeInfo{1, gfx::AttributeDataType::Short4, idFillExtrusionNormalEdVertexAttribute}, - AttributeInfo{2, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, - AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, - AttributeInfo{4, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute}, - AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute}, +const std::array FillExtrusionPatternShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced}, + AttributeInfo{1, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, + AttributeInfo{2, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, + AttributeInfo{3, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute}, + AttributeInfo{4, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute}, }; const std::array FillExtrusionPatternShaderSource::textures = { TextureInfo{0, idFillExtrusionImageTexture}, }; +// +// Fill extrusion pattern instanced + +using FillExtrusionPatternInstancedShaderSource = + ShaderSource; + +const std::array FillExtrusionPatternInstancedShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, +}; +const std::array FillExtrusionPatternInstancedShaderSource::instanceAttributes = { + AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced}, + AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionEdDiscardAttribute, idFillExtrusionInstanced}, + + // Data driven + AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute}, + AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute}, + AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute}, + AttributeInfo{6, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute}, +}; +const std::array FillExtrusionPatternInstancedShaderSource::textures = { + TextureInfo{0, idFillExtrusionImageTexture}, +}; + } // namespace shaders } // namespace mbgl diff --git a/src/mbgl/shaders/vulkan/shader_program.cpp b/src/mbgl/shaders/vulkan/shader_program.cpp index 8768108ab..2e080e480 100644 --- a/src/mbgl/shaders/vulkan/shader_program.cpp +++ b/src/mbgl/shaders/vulkan/shader_program.cpp @@ -244,14 +244,18 @@ bool ShaderProgram::hasTextures() const { textureBindings.begin(), textureBindings.end(), [](const auto& texture) { return texture.has_value(); }); } -void ShaderProgram::initAttribute(const shaders::AttributeInfo& info) { +void ShaderProgram::initVertexAttribute(const shaders::AttributeInfo& info) { const auto index = static_cast(info.index); #if !defined(NDEBUG) // Indexes must be unique, if there's a conflict check the `attributes` array in the shader vertexAttributes.visitAttributes([&](const gfx::VertexAttribute& attrib) { assert(attrib.getIndex() != index); }); - instanceAttributes.visitAttributes([&](const gfx::VertexAttribute& attrib) { assert(attrib.getIndex() != index); }); #endif vertexAttributes.set(info.id, index, info.dataType, 1); + + if (info.ubo != -1) { + auto& attrib = static_cast(*vertexAttributes.get(info.id)); + attrib.setUBO(info.ubo); + } } void ShaderProgram::initInstanceAttribute(const shaders::AttributeInfo& info) { @@ -260,9 +264,14 @@ void ShaderProgram::initInstanceAttribute(const shaders::AttributeInfo& info) { #if !defined(NDEBUG) // Indexes must not be reused by regular attributes or uniform blocks // More than one instance attribute can have the same index, if they share the block - vertexAttributes.visitAttributes([&](const gfx::VertexAttribute& attrib) { assert(attrib.getIndex() != index); }); + instanceAttributes.visitAttributes([&](const gfx::VertexAttribute& attrib) { assert(attrib.getIndex() != index); }); #endif instanceAttributes.set(info.id, index, info.dataType, 1); + + if (info.ubo != -1) { + auto& attrib = static_cast(*instanceAttributes.get(info.id)); + attrib.setUBO(info.ubo); + } } void ShaderProgram::initTexture(const shaders::TextureInfo& info) { diff --git a/src/mbgl/vulkan/buffer_resource.cpp b/src/mbgl/vulkan/buffer_resource.cpp index 5dc65f6c2..8c6ccf547 100644 --- a/src/mbgl/vulkan/buffer_resource.cpp +++ b/src/mbgl/vulkan/buffer_resource.cpp @@ -57,7 +57,8 @@ BufferResource::BufferResource( std::size_t totalSize = size; // TODO -> check avg minUniformBufferOffsetAlignment vs individual buffers - if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT || usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) { + if ((usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) == 0 && + (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT || usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) { const auto& backend = context.getBackend(); const auto& deviceProps = backend.getDeviceProperties(); @@ -127,30 +128,44 @@ BufferResource::BufferResource(BufferResource&& other) noexcept other.bufferAllocation = nullptr; } +BufferResource::BufferResource(const BufferResource& other) noexcept + : context(other.context), + size(other.size), + usage(other.usage), + version(other.version), + persistent(other.persistent), + bufferAllocation(other.bufferAllocation), + bufferWindowSize(other.bufferWindowSize), + bufferWindowVersions(other.bufferWindowVersions) {} + BufferResource::~BufferResource() noexcept { destroy(true); } void BufferResource::destroy(bool deferred) { - if (isValid()) { - context.threadSafeAccessRenderingStats([&](gfx::RenderingStats& stats) { - stats.numBuffers--; - - if (bufferWindowSize > 0) { - stats.memBuffers -= bufferWindowSize * context.getBackend().getMaxFrames(); - } else { - stats.memBuffers -= size; - } - }); - } - if (!bufferAllocation) { return; } + const size_t size_ = bufferWindowSize > 0 ? bufferWindowSize * bufferWindowVersions.size() : size; + if (deferred) { - context.enqueueDeletion([allocation = std::move(bufferAllocation)](auto&) mutable { allocation.reset(); }); + context.enqueueDeletion([size_, allocation = std::move(bufferAllocation)](auto& context_) mutable { + if (allocation.use_count() == 1) { + context_.threadSafeAccessRenderingStats([&](gfx::RenderingStats& stats) { + stats.numBuffers--; + stats.memBuffers -= size_; + }); + } + allocation.reset(); + }); } else { + if (bufferAllocation.use_count() == 1) { + context.threadSafeAccessRenderingStats([&](gfx::RenderingStats& stats) { + stats.numBuffers--; + stats.memBuffers -= size_; + }); + } bufferAllocation.reset(); } } @@ -159,6 +174,10 @@ BufferResource BufferResource::clone() const { return {context, contents(), size, usage, persistent}; } +BufferResource BufferResource::shared() const { + return BufferResource(*this); +} + BufferResource& BufferResource::operator=(BufferResource&& other) noexcept { assert(&context == &other.context); if (isValid()) { diff --git a/src/mbgl/vulkan/context.cpp b/src/mbgl/vulkan/context.cpp index ad665f198..53425fa64 100644 --- a/src/mbgl/vulkan/context.cpp +++ b/src/mbgl/vulkan/context.cpp @@ -99,7 +99,8 @@ void Context::initFrameResources() { descriptorPoolMap.emplace( DescriptorSetType::DrawableUniform, - DescriptorPoolGrowable(drawableUniformDescriptorPoolSize, 0, shaders::maxUBOCountPerDrawable, 0)); + DescriptorPoolGrowable( + drawableUniformDescriptorPoolSize, shaders::maxSSBOCountPerDrawable, shaders::maxUBOCountPerDrawable, 0)); descriptorPoolMap.emplace( DescriptorSetType::DrawableImage, @@ -125,18 +126,18 @@ void Context::initFrameResources() { } // force placeholder texture upload before any descriptor sets - (void)getDummyTexture(); + static_cast(getDummyTexture()); buildUniformDescriptorSetLayout( globalUniformDescriptorSetLayout, 0, 0, shaders::globalUBOCount, "GlobalUniformDescriptorSetLayout"); buildUniformDescriptorSetLayout(layerUniformDescriptorSetLayout, - shaders::globalUBOCount, + shaders::layerSSBOStartId, shaders::maxSSBOCountPerLayer, shaders::maxUBOCountPerLayer, "LayerUniformDescriptorSetLayout"); buildUniformDescriptorSetLayout(drawableUniformDescriptorSetLayout, - shaders::globalUBOCount, - 0, + shaders::drawableSSBOStartId, + shaders::maxSSBOCountPerDrawable, shaders::maxUBOCountPerDrawable, "DrawableUniformDescriptorSetLayout"); buildImageDescriptorSetLayout(); @@ -663,7 +664,7 @@ const std::unique_ptr& Context::getDummyTexture() { } void Context::buildUniformDescriptorSetLayout(vk::UniqueDescriptorSetLayout& layout, - size_t startId, + [[maybe_unused]] size_t startId, size_t storageCount, size_t uniformCount, const std::string& name) { @@ -673,6 +674,7 @@ void Context::buildUniformDescriptorSetLayout(vk::UniqueDescriptorSetLayout& lay if (startId + i != shaders::idDrawableReservedFragmentOnlyUBO) { stageFlags |= vk::ShaderStageFlagBits::eVertex; } + if (startId + i != shaders::idDrawableReservedVertexOnlyUBO) { stageFlags |= vk::ShaderStageFlagBits::eFragment; } diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 92de8aba2..8f373ac44 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -194,6 +194,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { if (impl->attributeBindings != attributeBindings_) { impl->attributeBindings = std::move(attributeBindings_); + + const auto& shaderImpl = static_cast(*shader); + setSharedBuffers(shaderImpl.getVertexAttributes(), impl->attributeBindings); } } @@ -219,6 +222,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { if (impl->instanceBindings != instanceBindings_) { impl->instanceBindings = std::move(instanceBindings_); + + const auto& shaderImpl = static_cast(*shader); + setSharedBuffers(shaderImpl.getInstanceAttributes(), impl->instanceBindings); } } @@ -358,6 +364,26 @@ gfx::UniformBufferArray& Drawable::mutableUniformBuffers() { return impl->uniformBuffers; } +void Drawable::setSharedBuffers(const gfx::VertexAttributeArray& attribs, const gfx::AttributeBindingArray& bindings) { + // set shared vertex/uniform buffers + attribs.visitAttributes([&](const gfx::VertexAttribute& attrib) { + const auto& vkAttrib = static_cast(attrib); + int ubo = vkAttrib.getUBO(); + + if (ubo == -1 || impl->uniformBuffers.get(ubo) != nullptr) { + return; + } + + const auto& binding = bindings[vkAttrib.getIndex()]; + if (!binding) { + return; + } + + const auto buffer = static_cast(binding->vertexBufferResource); + impl->uniformBuffers.set(ubo, std::make_shared(buffer->get().shared())); + }); +} + void Drawable::buildVulkanInputBindings() { MLN_TRACE_FUNC(); diff --git a/src/mbgl/vulkan/drawable_impl.hpp b/src/mbgl/vulkan/drawable_impl.hpp index 1f345dc0c..2da3d953a 100644 --- a/src/mbgl/vulkan/drawable_impl.hpp +++ b/src/mbgl/vulkan/drawable_impl.hpp @@ -24,8 +24,10 @@ using namespace platform; class Drawable::Impl final { public: Impl() - : uniformBuffers( - DescriptorSetType::DrawableUniform, shaders::globalUBOCount, 0, shaders::maxUBOCountPerDrawable) {} + : uniformBuffers(DescriptorSetType::DrawableUniform, + shaders::drawableSSBOStartId, + shaders::maxSSBOCountPerDrawable, + shaders::maxUBOCountPerDrawable) {} ~Impl() = default; diff --git a/src/mbgl/vulkan/layer_group.cpp b/src/mbgl/vulkan/layer_group.cpp index 3bcf1b0a9..80c20e37a 100644 --- a/src/mbgl/vulkan/layer_group.cpp +++ b/src/mbgl/vulkan/layer_group.cpp @@ -17,7 +17,7 @@ namespace vulkan { LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) : mbgl::LayerGroup(layerIndex_, initialCapacity, std::move(name_)), uniformBuffers(DescriptorSetType::Layer, - shaders::globalUBOCount, + shaders::layerSSBOStartId, shaders::maxSSBOCountPerLayer, shaders::maxUBOCountPerLayer) {} diff --git a/src/mbgl/vulkan/renderer_backend.cpp b/src/mbgl/vulkan/renderer_backend.cpp index 6c88f60d4..7382d2f9c 100644 --- a/src/mbgl/vulkan/renderer_backend.cpp +++ b/src/mbgl/vulkan/renderer_backend.cpp @@ -690,7 +690,9 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::FillOutlinePatternShader, shaders::BuiltIn::FillOutlineTriangulatedShader, shaders::BuiltIn::FillExtrusionShader, + shaders::BuiltIn::FillExtrusionInstancedShader, shaders::BuiltIn::FillExtrusionPatternShader, + shaders::BuiltIn::FillExtrusionPatternInstancedShader, shaders::BuiltIn::HeatmapShader, shaders::BuiltIn::HeatmapTextureShader, shaders::BuiltIn::HillshadeShader, diff --git a/src/mbgl/vulkan/upload_pass.cpp b/src/mbgl/vulkan/upload_pass.cpp index b91194b2d..59d42f8a6 100644 --- a/src/mbgl/vulkan/upload_pass.cpp +++ b/src/mbgl/vulkan/upload_pass.cpp @@ -50,6 +50,10 @@ void UploadPass::updateIndexBufferResource(gfx::IndexBufferResource& resource, c static_cast(resource).get().update(data, size, /*offset=*/0); } +BufferResource UploadPass::createBufferResource(const void* data, std::size_t size, size_t usage, bool persistent) { + return commandEncoder.context.createBuffer(data, size, usage, persistent); +} + struct VertexBuffer : public gfx::VertexBufferBase { ~VertexBuffer() override = default; @@ -59,7 +63,7 @@ struct VertexBuffer : public gfx::VertexBufferBase { static const std::unique_ptr noBuffer; const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVectorBasePtr& vec, - const gfx::BufferUsageType usage, + size_t usage, [[maybe_unused]] bool forceUpdate) { if (vec) { const auto* rawBufPtr = vec->getRawData(); @@ -81,7 +85,8 @@ const gfx::UniqueVertexBufferResource& UploadPass::getBuffer(const gfx::VertexVe // Otherwise, create a new one if (rawBufSize > 0) { auto buffer = std::make_unique(); - buffer->resource = createVertexBufferResource(rawBufPtr, rawBufSize, usage, /*persistent=*/false); + buffer->resource = std::make_unique( + createBufferResource(rawBufPtr, rawBufSize, usage, false)); vec->setBuffer(std::move(buffer)); auto* rawData = static_cast(vec->getBuffer()); @@ -100,7 +105,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( const std::vector&, const gfx::VertexAttributeArray& defaults, const gfx::VertexAttributeArray& overrides, - const gfx::BufferUsageType usage, + const gfx::BufferUsageType, const std::optional> lastUpdate, /*out*/ std::vector>&) { gfx::AttributeBindingArray bindings; @@ -128,7 +133,8 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( } // If the attribute references data shared with a bucket, get the corresponding buffer. - if (const auto& buffer = getBuffer(effectiveAttr.getSharedRawData(), usage, !lastUpdate)) { + if (const auto& buffer = getBuffer( + effectiveAttr.getSharedRawData(), defaultAttr.getBufferUsage(), !lastUpdate)) { assert(effectiveAttr.getSharedStride() * effectiveAttr.getSharedVertexOffset() < effectiveAttr.getSharedRawData()->getRawSize() * effectiveAttr.getSharedRawData()->getRawCount()); @@ -146,7 +152,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( // Otherwise, turn the data managed by the attribute into a buffer. if (const auto& buffer = VertexAttribute::getBuffer( - effectiveAttr, *this, gfx::BufferUsageType::StaticDraw, !lastUpdate)) { + effectiveAttr, *this, defaultAttr.getBufferUsage(), !lastUpdate)) { bindings[index] = { /*.attribute = */ {effectiveAttr.getDataType(), /*offset=*/0}, /*.vertexStride = */ static_cast(effectiveAttr.getStride()), diff --git a/src/mbgl/vulkan/vertex_attribute.cpp b/src/mbgl/vulkan/vertex_attribute.cpp index 5515efe8c..83585f6fa 100644 --- a/src/mbgl/vulkan/vertex_attribute.cpp +++ b/src/mbgl/vulkan/vertex_attribute.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -12,9 +13,17 @@ namespace mbgl { namespace vulkan { +size_t VertexAttribute::getBufferUsage() const { + if (ubo == -1) { + return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + } + + return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; +} + const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAttribute& attrib_, UploadPass& uploadPass, - const gfx::BufferUsageType usage, + size_t usage, bool forceUpdate) { if (!attrib_.getBuffer()) { auto& attrib = static_cast(attrib_); @@ -22,8 +31,8 @@ const gfx::UniqueVertexBufferResource& VertexAttribute::getBuffer(gfx::VertexAtt return uploadPass.getBuffer(attrib.sharedRawData, usage, forceUpdate); } else { if (!attrib.rawData.empty()) { - auto buffer = uploadPass.createVertexBufferResource( - attrib.rawData.data(), attrib.rawData.size(), usage, false); + auto buffer = std::make_unique( + uploadPass.createBufferResource(attrib.rawData.data(), attrib.rawData.size(), usage, false)); attrib.setBuffer(std::move(buffer)); attrib.setRawData({}); attrib_.setDirty(false);