Skip to content

Commit

Permalink
Merge pull request #364 from RagnarokResearchLab/272-dynamic-uniform-…
Browse files Browse the repository at this point in the history
…alignment

Make sure the selected dynamic uniform buffer alignment works on NVIDIA devices
  • Loading branch information
rdw-software authored Feb 6, 2024
2 parents f5129b2 + 8d321af commit d492584
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 15 deletions.
15 changes: 3 additions & 12 deletions Core/NativeClient/WebGPU/GPU.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local GPU = {
MAX_VERTEX_COUNT = 200000, -- Should be configurable (later)
MAX_TEXTURE_ARRAY_SIZE = 32,
MAX_BUFFER_SIZE = 256 * 1024 * 1024,
MAX_UNIFORM_BUFFER_BINDING_SIZE = 65536,
}

function GPU:CreateInstance()
Expand Down Expand Up @@ -78,18 +79,15 @@ function GPU:RequestLogicalDevice(adapter, options)
maxUniformBuffersPerShaderStage = 1, -- Camera properties (increase for material, soon?)
maxSampledTexturesPerShaderStage = GPU.MAX_TEXTURE_ARRAY_SIZE,
maxSamplersPerShaderStage = GPU.MAX_TEXTURE_ARRAY_SIZE,
maxUniformBufferBindingSize = 65536, -- DEFAULT
maxUniformBufferBindingSize = GPU.MAX_UNIFORM_BUFFER_BINDING_SIZE,
maxBindingsPerBindGroup = 2, -- Max. allowed binding index
maxDynamicUniformBuffersPerPipelineLayout = 1,
minStorageBufferOffsetAlignment = 32,
minUniformBufferOffsetAlignment = 32,
minUniformBufferOffsetAlignment = ffi.sizeof("mesh_uniform_t"),
},
}),
})

assert(supportedLimits.limits.minUniformBufferOffsetAlignment <= 32, "Dynamic uniform headaches will ensue")
self.minUniformBufferOffsetAlignment = supportedLimits.limits.minUniformBufferOffsetAlignment

local requestedDevice
local function onDeviceRequested(status, device, message, userdata)
local success = status == ffi.C.WGPURequestDeviceStatus_Success
Expand Down Expand Up @@ -129,11 +127,4 @@ function GPU:RequestLogicalDevice(adapter, options)
return requestedDevice, deviceDescriptor
end

function GPU:GetAlignedDynamicUniformBufferStride(uniformStructSizeInBytes)
local step = self.minUniformBufferOffsetAlignment
-- More headaches if the dynamic uniforms (e.g., widget transforms) are smaller than the minimum stride...
local divide_and_ceil = uniformStructSizeInBytes / step + (uniformStructSizeInBytes % step == 0 and 0 or 1)
return step * divide_and_ceil
end

return GPU
3 changes: 2 additions & 1 deletion Core/NativeClient/WebGPU/Pipelines/WidgetDrawingPipeline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local webgpu = require("webgpu")

local Device = require("Core.NativeClient.WebGPU.Device")

local GPU = require("Core.NativeClient.WebGPU.GPU")
local UniformBuffer = require("Core.NativeClient.WebGPU.UniformBuffer")

local binary_not = bit.bnot
Expand All @@ -12,7 +13,7 @@ local sizeof = ffi.sizeof

local WidgetDrawingPipeline = {
WGSL_SHADER_SOURCE_LOCATION = "Core/NativeClient/WebGPU/Shaders/UserInterfaceShader.wgsl",
MAX_WIDGET_COUNT = 2048, -- The default maxUniformBufferBindingSize allows for this many without optimizing further/removing padding/using other buffer types or even hardware instacing for the UI
MAX_WIDGET_COUNT = GPU.MAX_UNIFORM_BUFFER_BINDING_SIZE / sizeof("mesh_uniform_t"),
}

function WidgetDrawingPipeline:Construct(wgpuDeviceHandle, textureFormatID)
Expand Down
5 changes: 3 additions & 2 deletions Core/NativeClient/WebGPU/UniformBuffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ local UniformBuffer = {
} water_uniform_t;
typedef struct PerMeshData {
float translation[2]; // 8
float padding[6]; // 32
// Total size must be at least minUniformBufferOffsetAlignment bytes large (with 16 byte alignment)
float padding[62]; // 256
// Struct size must be aligned with minUniformBufferOffsetAlignment (GPU limit)
// Padding needs to be updated whenever the struct changes!
} mesh_uniform_t;
]],
}
Expand Down

0 comments on commit d492584

Please sign in to comment.