GPU: Add platform parameter for GPU architecture #112566
|
@ -55,6 +55,19 @@ typedef enum eGPUSupportLevel {
|
|||
GPU_SUPPORT_LEVEL_UNSUPPORTED,
|
||||
} eGPUSupportLevel;
|
||||
|
||||
typedef enum GPUArchitectureType {
|
||||
|
||||
/* Immediate Mode Renderer (IMR).
|
||||
Jeroen Bakker
commented
These terms are not clear. Think eGPUMemoryModel would be more appropriate as an GPU architecture is typically used to refer to a processor type or series. Possible values might be These terms are not clear.
If I look further in the code it is unified memory or not.
Think eGPUMemoryModel would be more appropriate as an GPU architecture is typically used to refer to a processor type or series. Possible values might be
GPU_MEMORY_MODEL_INTEGRATED
GPU_MEMORY_MODEL_DEDICATED
GPU_MEMORY_MODEL_UNIFIED
Clément Foucault
commented
I think it is more about the way how the chip is build to render. So it has nothing to do with the memory model. Some intel chip might have some dedicated memory but still work as tile renderer. I think it is more about the way how the chip is build to render. So it has nothing to do with the memory model. Some intel chip might have some dedicated memory but still work as tile renderer.
The memory model would also likely be a valid capability to expose, but would cover different use-cases. Currently, the use-case for architecture type would be to determine which implementation of virtual shadow map updating to use as per: #111283 (Metal: EEVEE Next: Optimize Virtual shadow maps for Apple Silicon). Granted, the memory model could be used to achieve the same switch, but the implementation of the technique is mostly depending on the architecture style of the GPU, as Clement outlined. It could still theoretically be possible to have either type of architecture with any other type of memory model. This architecture check may also be relevant for other APIs in future, especially also for windows machines running with Qualcomm Snapdragon GPUs. (Qualcomm is also a little iffy as technically these GPUs can also run in immediate mode, depending on the bits-per-pixel and workload being rendered) Perhaps it's a technicality atm, as atm, there is a correlation between tile-based architectures and system-on-chip Unified memory architecture, so I guess it depends which parameter best represents this. I see two options:
The memory model would also likely be a valid capability to expose, but would cover different use-cases.
Currently, the use-case for architecture type would be to determine which implementation of virtual shadow map updating to use as per: https://projects.blender.org/blender/blender/pulls/111283 (Metal: EEVEE Next: Optimize Virtual shadow maps for Apple Silicon).
Granted, the memory model could be used to achieve the same switch, but the implementation of the technique is mostly depending on the architecture style of the GPU, as Clement outlined.
It could still theoretically be possible to have either type of architecture with any other type of memory model.
This architecture check may also be relevant for other APIs in future, especially also for windows machines running with Qualcomm Snapdragon GPUs. (Qualcomm is also a little iffy as technically these GPUs can also run in immediate mode, depending on the bits-per-pixel and workload being rendered)
Perhaps it's a technicality atm, as atm, there is a correlation between tile-based architectures and system-on-chip Unified memory architecture, so I guess it depends which parameter best represents this.
I see two options:
1) Add both capabilities
2) Use eGPUMemoryModel with the assumption that a unified memory implies a tile-based renderer, which can use tile-shaders and on-tile per-pixel storage.
Jeroen Bakker
commented
In that case it makes more sense to have a GPU capability setting where we can check if it uses tiled rendering. As this is still an internal property think it is enough to use a bool. In that case it makes more sense to have a GPU capability setting where we can check if it uses tiled rendering. As this is still an internal property think it is enough to use a bool.
`GPU_tiled_renderer_support()` or something similar.
|
||||
* Typically, an IMR architecture will execute GPU work in sequence, rasterizing primitives in
|
||||
* order. */
|
||||
GPU_ARCHITECTURE_IMR = 0,
|
||||
|
||||
/* Tile-Based-Deferred-Renderer (TBDR).
|
||||
* A TBDR architecture will typically execute the vertex stage up-front for all primitives,
|
||||
* binning geometry into distinct tiled regions. Fragments will then be rasterized within
|
||||
* the bounds of one tile at a time. */
|
||||
GPU_ARCHITECTURE_TBDR = 1,
|
||||
} GPUArchitectureType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -74,6 +87,7 @@ const char *GPU_platform_renderer(void);
|
|||
const char *GPU_platform_version(void);
|
||||
const char *GPU_platform_support_level_key(void);
|
||||
const char *GPU_platform_gpu_name(void);
|
||||
GPUArchitectureType GPU_platform_architecture(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@ class DummyBackend : public GPUBackend {
|
|||
GPU_BACKEND_NONE,
|
||||
"Unknown",
|
||||
"",
|
||||
"");
|
||||
"",
|
||||
GPU_ARCHITECTURE_IMR);
|
||||
}
|
||||
void delete_resources() override {}
|
||||
void samplers_update() override {}
|
||||
|
|
|
@ -70,7 +70,8 @@ void GPUPlatformGlobal::init(eGPUDeviceType gpu_device,
|
|||
eGPUBackendType backend,
|
||||
const char *vendor_str,
|
||||
const char *renderer_str,
|
||||
const char *version_str)
|
||||
const char *version_str,
|
||||
GPUArchitectureType arch_type)
|
||||
{
|
||||
this->clear();
|
||||
|
||||
|
@ -91,6 +92,7 @@ void GPUPlatformGlobal::init(eGPUDeviceType gpu_device,
|
|||
this->support_key = create_key(gpu_support_level, vendor, renderer, version);
|
||||
this->gpu_name = create_gpu_name(vendor, renderer, version);
|
||||
this->backend = backend;
|
||||
this->architecture_type = arch_type;
|
||||
}
|
||||
|
||||
void GPUPlatformGlobal::clear()
|
||||
|
@ -149,6 +151,12 @@ const char *GPU_platform_gpu_name()
|
|||
return GPG.gpu_name;
|
||||
}
|
||||
|
||||
GPUArchitectureType GPU_platform_architecture()
|
||||
{
|
||||
BLI_assert(GPG.initialized);
|
||||
return GPG.architecture_type;
|
||||
}
|
||||
|
||||
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
|
||||
{
|
||||
return GPU_type_matches_ex(device, os, driver, GPU_BACKEND_ANY);
|
||||
|
|
|
@ -25,6 +25,7 @@ class GPUPlatformGlobal {
|
|||
char *support_key = nullptr;
|
||||
char *gpu_name = nullptr;
|
||||
eGPUBackendType backend = GPU_BACKEND_NONE;
|
||||
GPUArchitectureType architecture_type = GPU_ARCHITECTURE_IMR;
|
||||
|
||||
public:
|
||||
void init(eGPUDeviceType gpu_device,
|
||||
|
@ -34,7 +35,8 @@ class GPUPlatformGlobal {
|
|||
eGPUBackendType backend,
|
||||
const char *vendor_str,
|
||||
const char *renderer_str,
|
||||
const char *version_str);
|
||||
const char *version_str,
|
||||
GPUArchitectureType arch_type);
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
|
|
@ -194,6 +194,8 @@ void MTLBackend::platform_init(MTLContext *ctx)
|
|||
if (G.debug & G_DEBUG_GPU) {
|
||||
printf("METAL API - DETECTED GPU: %s\n", vendor);
|
||||
}
|
||||
GPUArchitectureType architecture_type = (mtl_device.hasUnifiedMemory) ? GPU_ARCHITECTURE_TBDR :
|
||||
GPU_ARCHITECTURE_IMR;
|
||||
|
||||
/* macOS is the only supported platform, but check to ensure we are not building with Metal
|
||||
* enablement on another platform. */
|
||||
|
@ -240,7 +242,15 @@ void MTLBackend::platform_init(MTLContext *ctx)
|
|||
printf("Renderer: %s\n", renderer);
|
||||
}
|
||||
|
||||
GPG.init(device, os, driver, support_level, GPU_BACKEND_METAL, vendor, renderer, version);
|
||||
GPG.init(device,
|
||||
os,
|
||||
driver,
|
||||
support_level,
|
||||
GPU_BACKEND_METAL,
|
||||
vendor,
|
||||
renderer,
|
||||
version,
|
||||
architecture_type);
|
||||
}
|
||||
|
||||
void MTLBackend::platform_exit()
|
||||
|
|
|
@ -163,7 +163,15 @@ void GLBackend::platform_init()
|
|||
}
|
||||
}
|
||||
|
||||
GPG.init(device, os, driver, support_level, GPU_BACKEND_OPENGL, vendor, renderer, version);
|
||||
GPG.init(device,
|
||||
os,
|
||||
driver,
|
||||
support_level,
|
||||
GPU_BACKEND_OPENGL,
|
||||
vendor,
|
||||
renderer,
|
||||
version,
|
||||
GPU_ARCHITECTURE_IMR);
|
||||
}
|
||||
|
||||
void GLBackend::platform_exit()
|
||||
|
|
|
@ -50,7 +50,8 @@ void VKBackend::platform_init()
|
|||
GPU_BACKEND_VULKAN,
|
||||
"",
|
||||
"",
|
||||
"");
|
||||
"",
|
||||
GPU_ARCHITECTURE_IMR);
|
||||
}
|
||||
|
||||
void VKBackend::platform_init(const VKDevice &device)
|
||||
|
@ -72,7 +73,8 @@ void VKBackend::platform_init(const VKDevice &device)
|
|||
GPU_BACKEND_VULKAN,
|
||||
vendor_name.c_str(),
|
||||
properties.deviceName,
|
||||
driver_version.c_str());
|
||||
driver_version.c_str(),
|
||||
GPU_ARCHITECTURE_IMR);
|
||||
}
|
||||
|
||||
void VKBackend::detect_workarounds(VKDevice &device)
|
||||
|
|
do not use
e
prefix. This is from an older codestyle no longer in place.Ah gotcha! Will update thanks, had originally just aimed to be consistent with the other Enums declared in this file.