diff options
author | Jason Fielder <jason_apple> | 2022-09-01 23:14:18 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-09-01 23:18:02 +0300 |
commit | ac07fb38a1b35fa156b2d0901eb35cd65ed73903 (patch) | |
tree | 2fe5a9b69c5c8bf04818e8b2cde0393e960a12ca /source/blender/gpu | |
parent | 5f4409b02ef7c54089ff1b491e008d4b86c030f4 (diff) |
Metal: Minimum per-vertex stride, 3D texture size + Transform feedback GPUCapabilities expansion.
- Adding in compatibility paths to support minimum per-vertex strides for vertex formats. OpenGL supports a minimum stride of 1 byte, in Metal, this minimum stride is 4 bytes. Meaing a vertex format must be atleast 4-bytes in size.
- Replacing transform feedback compile-time check to conditional look-up, given TF is supported on macOS with Metal.
- 3D texture size safety check added as a general capability, rather than being in the gl backend only. Also required for Metal.
Authored by Apple: Michael Parkin-White
Ref T96261
Reviewed By: fclem
Maniphest Tasks: T96261
Differential Revision: https://developer.blender.org/D14510
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/GPU_capabilities.h | 5 | ||||
-rw-r--r-- | source/blender/gpu/GPU_vertex_buffer.h | 16 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_capabilities.cc | 20 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.cc | 7 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_vertex_buffer.cc | 22 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_vertex_buffer_private.hh | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_vertex_format.cc | 15 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_vertex_format_private.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 12 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.cc | 2 |
11 files changed, 96 insertions, 15 deletions
diff --git a/source/blender/gpu/GPU_capabilities.h b/source/blender/gpu/GPU_capabilities.h index aa01f446b9b..61c60f336e1 100644 --- a/source/blender/gpu/GPU_capabilities.h +++ b/source/blender/gpu/GPU_capabilities.h @@ -16,6 +16,7 @@ extern "C" { #endif int GPU_max_texture_size(void); +int GPU_max_texture_3d_size(void); int GPU_max_texture_layers(void); int GPU_max_textures(void); int GPU_max_textures_vert(void); @@ -31,6 +32,7 @@ int GPU_max_vertex_attribs(void); int GPU_max_varying_floats(void); int GPU_max_shader_storage_buffer_bindings(void); int GPU_max_compute_shader_storage_blocks(void); +int GPU_max_samplers(void); int GPU_extensions_len(void); const char *GPU_extension_get(int i); @@ -57,6 +59,9 @@ void GPU_mem_stats_get(int *totalmem, int *freemem); */ bool GPU_stereo_quadbuffer_support(void); +int GPU_minimum_per_vertex_stride(void); +bool GPU_transform_feedback_support(void); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index 722ef878271..d3c1bd8145d 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -40,12 +40,20 @@ extern "C" { typedef enum { /* can be extended to support more types */ - GPU_USAGE_STREAM, - GPU_USAGE_STATIC, /* do not keep data in memory */ - GPU_USAGE_DYNAMIC, - GPU_USAGE_DEVICE_ONLY, /* Do not do host->device data transfers. */ + GPU_USAGE_STREAM = 0, + GPU_USAGE_STATIC = 1, /* do not keep data in memory */ + GPU_USAGE_DYNAMIC = 2, + GPU_USAGE_DEVICE_ONLY = 3, /* Do not do host->device data transfers. */ + + /** Extended usage flags. */ + /* Flag for vertex buffers used for textures. Skips additional padding/compaction to ensure + * format matches the texture exactly. Can be masked with other properties, and is stripped + * during VertBuf::init. */ + GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY = 1 << 3, } GPUUsageType; +ENUM_OPERATORS(GPUUsageType, GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY); + /** Opaque type hiding blender::gpu::VertBuf. */ typedef struct GPUVertBuf GPUVertBuf; diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index 73f94ecfb1b..e584b757a05 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -33,6 +33,11 @@ int GPU_max_texture_size() return GCaps.max_texture_size; } +int GPU_max_texture_3d_size(void) +{ + return GCaps.max_texture_3d_size; +} + int GPU_texture_size_with_limit(int res) { int size = GPU_max_texture_size(); @@ -115,6 +120,11 @@ const char *GPU_extension_get(int i) return GCaps.extension_get ? GCaps.extension_get(i) : "\0"; } +int GPU_max_samplers() +{ + return GCaps.max_samplers; +} + bool GPU_mip_render_workaround() { return GCaps.mip_render_workaround; @@ -176,6 +186,16 @@ int GPU_max_compute_shader_storage_blocks() return GCaps.max_compute_shader_storage_blocks; } +int GPU_minimum_per_vertex_stride(void) +{ + return GCaps.minimum_per_vertex_stride; +} + +bool GPU_transform_feedback_support(void) +{ + return GCaps.transform_feedback_support; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index 65daa416cae..bec8b8a0df3 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -360,6 +360,13 @@ GPUTexture *GPU_texture_create_compressed_2d( GPUTexture *GPU_texture_create_from_vertbuf(const char *name, GPUVertBuf *vert) { +#ifndef NDEBUG + /* Vertex buffers used for texture buffers must be flagged with: + * GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY. */ + BLI_assert_msg(unwrap(vert)->extended_usage_ & GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY, + "Vertex Buffers used for textures should have usage flag " + "GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY."); +#endif eGPUTextureFormat tex_format = to_texture_format(GPU_vertbuf_get_format(vert)); Texture *tex = GPUBackend::get()->texture_alloc(name); diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index 0dbd565291b..a441cfe2fb8 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -40,10 +40,21 @@ VertBuf::~VertBuf() void VertBuf::init(const GPUVertFormat *format, GPUUsageType usage) { - usage_ = usage; + /* Strip extended usage flags. */ + usage_ = usage & ~GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; +#ifndef NDEBUG + /* Store extended usage. */ + extended_usage_ = usage; +#endif flag = GPU_VERTBUF_DATA_DIRTY; GPU_vertformat_copy(&this->format, format); - if (!format->packed) { + /* Avoid packing vertex formats which are used for texture buffers. + * These cases use singular types and do not need packing. They must + * also not have increased alignment padding to the minimum per-vertex stride. */ + if (usage & GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY) { + VertexFormat_texture_buffer_pack(&this->format); + } + if (!this->format.packed) { VertexFormat_pack(&this->format); } flag |= GPU_VERTBUF_INIT; @@ -62,6 +73,10 @@ VertBuf *VertBuf::duplicate() *dst = *this; /* Almost full copy... */ dst->handle_refcount_ = 1; + /* Metadata. */ +#ifndef NDEBUG + dst->extended_usage_ = extended_usage_; +#endif /* Duplicate all needed implementation specifics data. */ this->duplicate_data(dst); return dst; @@ -192,6 +207,7 @@ void GPU_vertbuf_data_len_set(GPUVertBuf *verts_, uint v_len) void GPU_vertbuf_attr_set(GPUVertBuf *verts_, uint a_idx, uint v_idx, const void *data) { VertBuf *verts = unwrap(verts_); + BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY); const GPUVertFormat *format = &verts->format; const GPUVertAttr *a = &format->attrs[a_idx]; BLI_assert(v_idx < verts->vertex_alloc); @@ -215,6 +231,7 @@ void GPU_vertbuf_attr_fill(GPUVertBuf *verts_, uint a_idx, const void *data) void GPU_vertbuf_vert_set(GPUVertBuf *verts_, uint v_idx, const void *data) { VertBuf *verts = unwrap(verts_); + BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY); const GPUVertFormat *format = &verts->format; BLI_assert(v_idx < verts->vertex_alloc); BLI_assert(verts->data != nullptr); @@ -225,6 +242,7 @@ void GPU_vertbuf_vert_set(GPUVertBuf *verts_, uint v_idx, const void *data) void GPU_vertbuf_attr_fill_stride(GPUVertBuf *verts_, uint a_idx, uint stride, const void *data) { VertBuf *verts = unwrap(verts_); + BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY); const GPUVertFormat *format = &verts->format; const GPUVertAttr *a = &format->attrs[a_idx]; BLI_assert(a_idx < format->attr_len); diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh index a7920bacaec..f20f6caf6de 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh @@ -31,6 +31,11 @@ class VertBuf { /** NULL indicates data in VRAM (unmapped) */ uchar *data = nullptr; +#ifndef NDEBUG + /** Usage including extended usage flags. */ + GPUUsageType extended_usage_ = GPU_USAGE_STATIC; +#endif + protected: /** Usage hint for GL optimization. */ GPUUsageType usage_ = GPU_USAGE_STATIC; @@ -83,6 +88,11 @@ class VertBuf { } } + GPUUsageType get_usage_type() const + { + return usage_; + } + virtual void update_sub(uint start, uint len, const void *data) = 0; virtual const void *read() const = 0; virtual void *unmap(const void *mapped_data) const = 0; diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index c16c06c1421..5c21bc313eb 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -8,6 +8,8 @@ */ #include "GPU_vertex_format.h" +#include "GPU_capabilities.h" + #include "gpu_shader_create_info.hh" #include "gpu_shader_private.hh" #include "gpu_vertex_format_private.h" @@ -68,7 +70,7 @@ static uint attr_size(const GPUVertAttr *a) return a->comp_len * comp_size(static_cast<GPUVertCompType>(a->comp_type)); } -static uint attr_align(const GPUVertAttr *a) +static uint attr_align(const GPUVertAttr *a, uint minimum_stride) { if (a->comp_type == GPU_COMP_I10) { return 4; /* always packed as 10_10_10_2 */ @@ -78,7 +80,10 @@ static uint attr_align(const GPUVertAttr *a) return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */ } - return c; /* most fetches are ok if components are naturally aligned */ + /* Most fetches are ok if components are naturally aligned. + * However, in Metal,the minimum supported per-vertex stride is 4, + * so we must query the GPU and pad out the size accordingly. */ + return max_ii(minimum_stride, c); } uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len) @@ -308,7 +313,7 @@ static void show_pack(uint a_idx, uint size, uint pad) } #endif -void VertexFormat_pack(GPUVertFormat *format) +static void VertexFormat_pack_impl(GPUVertFormat *format, uint minimum_stride) { GPUVertAttr *a0 = &format->attrs[0]; a0->offset = 0; @@ -320,7 +325,7 @@ void VertexFormat_pack(GPUVertFormat *format) for (uint a_idx = 1; a_idx < format->attr_len; a_idx++) { GPUVertAttr *a = &format->attrs[a_idx]; - uint mid_padding = padding(offset, attr_align(a)); + uint mid_padding = padding(offset, attr_align(a, minimum_stride)); offset += mid_padding; a->offset = offset; offset += a->size; @@ -330,7 +335,7 @@ void VertexFormat_pack(GPUVertFormat *format) #endif } - uint end_padding = padding(offset, attr_align(a0)); + uint end_padding = padding(offset, attr_align(a0, minimum_stride)); #if PACK_DEBUG show_pack(0, 0, end_padding); diff --git a/source/blender/gpu/intern/gpu_vertex_format_private.h b/source/blender/gpu/intern/gpu_vertex_format_private.h index 0f8a869f6df..430008b4cb9 100644 --- a/source/blender/gpu/intern/gpu_vertex_format_private.h +++ b/source/blender/gpu/intern/gpu_vertex_format_private.h @@ -16,6 +16,7 @@ extern "C" { struct GPUVertFormat; void VertexFormat_pack(struct GPUVertFormat *format); +void VertexFormat_texture_buffer_pack(struct GPUVertFormat *format); uint padding(uint offset, uint alignment); uint vertex_buffer_size(const struct GPUVertFormat *format, uint vertex_len); diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 24ca8c25bc0..2375e78d9f1 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -386,6 +386,11 @@ static void detect_workarounds() } } + /* Disable TF on macOS. */ + if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) { + GCaps.transform_feedback_support = false; + } + /* Some Intel drivers have issues with using mips as frame-buffer targets if * GL_TEXTURE_MAX_LEVEL is higher than the target MIP. * Only check at the end after all other workarounds because this uses the drawing code. @@ -431,7 +436,6 @@ static void detect_workarounds() /** Internal capabilities. */ GLint GLContext::max_cubemap_size = 0; -GLint GLContext::max_texture_3d_size = 0; GLint GLContext::max_ubo_binds = 0; GLint GLContext::max_ubo_size = 0; GLint GLContext::max_ssbo_binds = 0; @@ -499,6 +503,8 @@ void GLBackend::capabilities_init() GCaps.shader_draw_parameters_support = epoxy_has_gl_extension("GL_ARB_shader_draw_parameters"); GCaps.compute_shader_support = epoxy_has_gl_extension("GL_ARB_compute_shader") && epoxy_gl_version() >= 43; + GCaps.max_samplers = GCaps.max_textures; + if (GCaps.compute_shader_support) { glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &GCaps.max_work_group_count[0]); glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &GCaps.max_work_group_count[1]); @@ -512,8 +518,10 @@ void GLBackend::capabilities_init() } GCaps.shader_storage_buffer_objects_support = epoxy_has_gl_extension( "GL_ARB_shader_storage_buffer_object"); + GCaps.transform_feedback_support = true; + /* GL specific capabilities. */ - glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size); + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GCaps.max_texture_3d_size); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size); glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GLContext::max_ubo_binds); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size); diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 2f8c2b762f8..1d413750fd4 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -40,7 +40,6 @@ class GLContext : public Context { /** Capabilities. */ static GLint max_cubemap_size; - static GLint max_texture_3d_size; static GLint max_ubo_size; static GLint max_ubo_binds; static GLint max_ssbo_size; diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index 2ce205353a3..02fc7dfdb5f 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -603,7 +603,7 @@ bool GLTexture::proxy_check(int mip) { /* Manual validation first, since some implementation have issues with proxy creation. */ int max_size = GPU_max_texture_size(); - int max_3d_size = GLContext::max_texture_3d_size; + int max_3d_size = GPU_max_texture_3d_size(); int max_cube_size = GLContext::max_cubemap_size; int size[3] = {1, 1, 1}; this->mip_size_get(mip, size); |