Simplify uniform padding in Metal (Ganesh).
Previously, we would pad Metal uniforms to the nearest 16-byte size if they contained a float3, float4, or matrix type. This does not appear to be necessary (all tests pass without this level of padding). Since Metal is C++ based, it does have *some* struct padding, based on the basic type in the structure with the highest bit-width. Rather than track this amount, we just assume that it is 8 and round up Metal uniform blocks to the nearest 8-byte size. This will ~never be larger than our previous padding, since a typical Skia shader will generally always include a float2 uniform or larger (e.g. RTFlip is a float2), and will probably be tighter than before since most shaders include a color (float3/float4) or matrix uniform. Change-Id: Ic8dd49f33cb81a24a6415e9ba6e91c9f6faeb1b1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/556216 Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
6d57262159
commit
eaecd17d7a
@ -381,12 +381,15 @@ static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
|
|||||||
return mtlColorAttachment;
|
return mtlColorAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment) {
|
static uint32_t buffer_size(uint32_t offset) {
|
||||||
// Metal expects the buffer to be padded at the end according to the alignment
|
// Metal uses C++ padding rules, so we round up the buffer size if it's not evenly divisible by
|
||||||
// of the largest element in the buffer.
|
// eight. The padding is dictated by the highest-bit-width basic type in the struct.
|
||||||
uint32_t offsetDiff = offset & maxAlignment;
|
// In practice, this will probably be four (float), but on the off chance we ever use a double
|
||||||
|
// or a pointer, we pad to eight.
|
||||||
|
constexpr uint32_t kMaxAlignment = 7;
|
||||||
|
uint32_t offsetDiff = offset & kMaxAlignment;
|
||||||
if (offsetDiff != 0) {
|
if (offsetDiff != 0) {
|
||||||
offsetDiff = maxAlignment - offsetDiff + 1;
|
offsetDiff = kMaxAlignment - offsetDiff + 1;
|
||||||
}
|
}
|
||||||
return offset + offsetDiff;
|
return offset + offsetDiff;
|
||||||
}
|
}
|
||||||
@ -713,14 +716,12 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(
|
|||||||
|
|
||||||
sk_sp<GrMtlRenderPipeline> renderPipeline = GrMtlRenderPipeline::Make(pipelineState);
|
sk_sp<GrMtlRenderPipeline> renderPipeline = GrMtlRenderPipeline::Make(pipelineState);
|
||||||
|
|
||||||
uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
|
|
||||||
fUniformHandler.fCurrentUBOMaxAlignment);
|
|
||||||
return new GrMtlPipelineState(fGpu,
|
return new GrMtlPipelineState(fGpu,
|
||||||
std::move(renderPipeline),
|
std::move(renderPipeline),
|
||||||
pipelineDescriptor.colorAttachments[0].pixelFormat,
|
pipelineDescriptor.colorAttachments[0].pixelFormat,
|
||||||
fUniformHandles,
|
fUniformHandles,
|
||||||
fUniformHandler.fUniforms,
|
fUniformHandler.fUniforms,
|
||||||
bufferSize,
|
buffer_size(fUniformHandler.fCurrentUBOOffset),
|
||||||
(uint32_t)fUniformHandler.numSamplers(),
|
(uint32_t)fUniformHandler.numSamplers(),
|
||||||
std::move(fGPImpl),
|
std::move(fGPImpl),
|
||||||
std::move(fXPImpl),
|
std::move(fXPImpl),
|
||||||
|
@ -58,9 +58,7 @@ private:
|
|||||||
: INHERITED(program)
|
: INHERITED(program)
|
||||||
, fUniforms(kUniformsPerBlock)
|
, fUniforms(kUniformsPerBlock)
|
||||||
, fSamplers(kUniformsPerBlock)
|
, fSamplers(kUniformsPerBlock)
|
||||||
, fCurrentUBOOffset(0)
|
, fCurrentUBOOffset(0) {}
|
||||||
, fCurrentUBOMaxAlignment(0x0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
UniformHandle internalAddUniformArray(const GrProcessor* owner,
|
UniformHandle internalAddUniformArray(const GrProcessor* owner,
|
||||||
uint32_t visibility,
|
uint32_t visibility,
|
||||||
@ -98,7 +96,6 @@ private:
|
|||||||
SkTArray<skgpu::Swizzle> fSamplerSwizzles;
|
SkTArray<skgpu::Swizzle> fSamplerSwizzles;
|
||||||
|
|
||||||
uint32_t fCurrentUBOOffset;
|
uint32_t fCurrentUBOOffset;
|
||||||
uint32_t fCurrentUBOMaxAlignment;
|
|
||||||
|
|
||||||
friend class GrMtlPipelineStateBuilder;
|
friend class GrMtlPipelineStateBuilder;
|
||||||
|
|
||||||
|
@ -156,13 +156,9 @@ static inline uint32_t sksltype_to_mtl_size(SkSLType type) {
|
|||||||
// taking into consideration all alignment requirements. The uniformOffset is set to the offset for
|
// taking into consideration all alignment requirements. The uniformOffset is set to the offset for
|
||||||
// the new uniform, and currentOffset is updated to be the offset to the end of the new uniform.
|
// the new uniform, and currentOffset is updated to be the offset to the end of the new uniform.
|
||||||
static uint32_t get_ubo_aligned_offset(uint32_t* currentOffset,
|
static uint32_t get_ubo_aligned_offset(uint32_t* currentOffset,
|
||||||
uint32_t* maxAlignment,
|
|
||||||
SkSLType type,
|
SkSLType type,
|
||||||
int arrayCount) {
|
int arrayCount) {
|
||||||
uint32_t alignmentMask = sksltype_to_alignment_mask(type);
|
uint32_t alignmentMask = sksltype_to_alignment_mask(type);
|
||||||
if (alignmentMask > *maxAlignment) {
|
|
||||||
*maxAlignment = alignmentMask;
|
|
||||||
}
|
|
||||||
uint32_t offsetDiff = *currentOffset & alignmentMask;
|
uint32_t offsetDiff = *currentOffset & alignmentMask;
|
||||||
if (offsetDiff != 0) {
|
if (offsetDiff != 0) {
|
||||||
offsetDiff = alignmentMask - offsetDiff + 1;
|
offsetDiff = alignmentMask - offsetDiff + 1;
|
||||||
@ -200,8 +196,7 @@ GrGLSLUniformHandler::UniformHandle GrMtlUniformHandler::internalAddUniformArray
|
|||||||
}
|
}
|
||||||
SkString resolvedName = fProgramBuilder->nameVariable(prefix, name, mangleName);
|
SkString resolvedName = fProgramBuilder->nameVariable(prefix, name, mangleName);
|
||||||
|
|
||||||
uint32_t offset = get_ubo_aligned_offset(&fCurrentUBOOffset, &fCurrentUBOMaxAlignment,
|
uint32_t offset = get_ubo_aligned_offset(&fCurrentUBOOffset, type, arrayCount);
|
||||||
type, arrayCount);
|
|
||||||
SkString layoutQualifier;
|
SkString layoutQualifier;
|
||||||
layoutQualifier.appendf("offset=%d", offset);
|
layoutQualifier.appendf("offset=%d", offset);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user