2023-08-16 00:20:26 +10:00
/* SPDX-FileCopyrightText: 2023 Blender Authors
2023-05-31 16:19:06 +02:00
*
* SPDX - License - Identifier : GPL - 2.0 - or - later */
2022-04-12 18:28:27 -03:00
/** \file
* \ ingroup bpygpu
*
* - Use ` bpygpu_ ` for local API .
* - Use ` BPyGPU ` for public API .
*/
# include <Python.h>
# include "BLI_utildefines.h"
2024-03-23 01:24:18 +01:00
# include "GPU_shader.hh"
2022-04-12 18:28:27 -03:00
# include "intern/gpu_shader_create_info.hh"
2024-09-24 15:25:36 +02:00
# include "../generic/py_capi_utils.hh"
# include "../generic/python_compat.hh"
2022-04-12 18:28:27 -03:00
2024-03-23 10:06:45 -04:00
# include "gpu_py_shader.hh" /* own include */
# include "gpu_py_texture.hh"
2022-04-12 18:28:27 -03:00
2023-11-23 14:23:26 +01:00
# define USE_PYGPU_SHADER_INFO_IMAGE_METHOD
2022-04-12 18:28:27 -03:00
2025-03-31 12:37:56 +02:00
using blender : : gpu : : shader : : DepthWrite ;
2022-04-12 18:28:27 -03:00
using blender : : gpu : : shader : : DualBlend ;
using blender : : gpu : : shader : : Frequency ;
using blender : : gpu : : shader : : ImageType ;
using blender : : gpu : : shader : : ShaderCreateInfo ;
using blender : : gpu : : shader : : StageInterfaceInfo ;
using blender : : gpu : : shader : : Type ;
# ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
using blender : : gpu : : shader : : Qualifier ;
# define PYDOC_QUALIFIERS \
2022-04-13 22:38:16 +10:00
" - ``NO_RESTRICT`` \n " \
" - ``READ`` \n " \
" - ``WRITE`` \n "
2023-12-17 16:24:36 +11:00
static const PyC_FlagSet pygpu_qualifiers [ ] = {
2025-04-24 14:38:13 +02:00
{ int ( Qualifier : : no_restrict ) , " NO_RESTRICT " } ,
{ int ( Qualifier : : read ) , " READ " } ,
{ int ( Qualifier : : write ) , " WRITE " } ,
2022-04-12 18:28:27 -03:00
{ 0 , nullptr } ,
} ;
# endif
# define PYDOC_TYPE_LIST \
2022-04-13 22:38:16 +10:00
" - ``FLOAT`` \n " \
" - ``VEC2`` \n " \
" - ``VEC3`` \n " \
" - ``VEC4`` \n " \
" - ``MAT3`` \n " \
" - ``MAT4`` \n " \
" - ``UINT`` \n " \
" - ``UVEC2`` \n " \
" - ``UVEC3`` \n " \
" - ``UVEC4`` \n " \
" - ``INT`` \n " \
" - ``IVEC2`` \n " \
" - ``IVEC3`` \n " \
" - ``IVEC4`` \n " \
" - ``BOOL`` \n "
2023-06-03 08:36:28 +10:00
const PyC_StringEnumItems pygpu_attrtype_items [ ] = {
2025-04-11 22:39:01 +02:00
{ int ( Type : : float_t ) , " FLOAT " } ,
{ int ( Type : : float2_t ) , " VEC2 " } ,
{ int ( Type : : float3_t ) , " VEC3 " } ,
{ int ( Type : : float4_t ) , " VEC4 " } ,
{ int ( Type : : float3x3_t ) , " MAT3 " } ,
{ int ( Type : : float4x4_t ) , " MAT4 " } ,
{ int ( Type : : uint_t ) , " UINT " } ,
{ int ( Type : : uint2_t ) , " UVEC2 " } ,
{ int ( Type : : uint3_t ) , " UVEC3 " } ,
{ int ( Type : : uint4_t ) , " UVEC4 " } ,
{ int ( Type : : int_t ) , " INT " } ,
{ int ( Type : : int2_t ) , " IVEC2 " } ,
{ int ( Type : : int3_t ) , " IVEC3 " } ,
{ int ( Type : : int4_t ) , " IVEC4 " } ,
{ int ( Type : : bool_t ) , " BOOL " } ,
2022-04-12 18:28:27 -03:00
{ 0 , nullptr } ,
} ;
# define PYDOC_IMAGE_TYPES \
2022-04-13 22:38:16 +10:00
" - ``FLOAT_BUFFER`` \n " \
" - ``FLOAT_1D`` \n " \
" - ``FLOAT_1D_ARRAY`` \n " \
" - ``FLOAT_2D`` \n " \
" - ``FLOAT_2D_ARRAY`` \n " \
" - ``FLOAT_3D`` \n " \
" - ``FLOAT_CUBE`` \n " \
" - ``FLOAT_CUBE_ARRAY`` \n " \
" - ``INT_BUFFER`` \n " \
" - ``INT_1D`` \n " \
" - ``INT_1D_ARRAY`` \n " \
" - ``INT_2D`` \n " \
" - ``INT_2D_ARRAY`` \n " \
" - ``INT_3D`` \n " \
" - ``INT_CUBE`` \n " \
" - ``INT_CUBE_ARRAY`` \n " \
" - ``UINT_BUFFER`` \n " \
" - ``UINT_1D`` \n " \
" - ``UINT_1D_ARRAY`` \n " \
" - ``UINT_2D`` \n " \
" - ``UINT_2D_ARRAY`` \n " \
" - ``UINT_3D`` \n " \
" - ``UINT_CUBE`` \n " \
" - ``UINT_CUBE_ARRAY`` \n " \
" - ``SHADOW_2D`` \n " \
" - ``SHADOW_2D_ARRAY`` \n " \
" - ``SHADOW_CUBE`` \n " \
" - ``SHADOW_CUBE_ARRAY`` \n " \
" - ``DEPTH_2D`` \n " \
" - ``DEPTH_2D_ARRAY`` \n " \
" - ``DEPTH_CUBE`` \n " \
" - ``DEPTH_CUBE_ARRAY`` \n "
2023-06-03 08:36:28 +10:00
static const PyC_StringEnumItems pygpu_imagetype_items [ ] = {
2025-04-24 14:38:13 +02:00
{ int ( ImageType : : FloatBuffer ) , " FLOAT_BUFFER " } ,
{ int ( ImageType : : Float1D ) , " FLOAT_1D " } ,
{ int ( ImageType : : Float1DArray ) , " FLOAT_1D_ARRAY " } ,
{ int ( ImageType : : Float2D ) , " FLOAT_2D " } ,
{ int ( ImageType : : Float2DArray ) , " FLOAT_2D_ARRAY " } ,
{ int ( ImageType : : Float3D ) , " FLOAT_3D " } ,
{ int ( ImageType : : FloatCube ) , " FLOAT_CUBE " } ,
{ int ( ImageType : : FloatCubeArray ) , " FLOAT_CUBE_ARRAY " } ,
{ int ( ImageType : : IntBuffer ) , " INT_BUFFER " } ,
{ int ( ImageType : : Int1D ) , " INT_1D " } ,
{ int ( ImageType : : Int1DArray ) , " INT_1D_ARRAY " } ,
{ int ( ImageType : : Int2D ) , " INT_2D " } ,
{ int ( ImageType : : Int2DArray ) , " INT_2D_ARRAY " } ,
{ int ( ImageType : : Int3D ) , " INT_3D " } ,
{ int ( ImageType : : IntCube ) , " INT_CUBE " } ,
{ int ( ImageType : : IntCubeArray ) , " INT_CUBE_ARRAY " } ,
{ int ( ImageType : : AtomicInt2D ) , " INT_2D_ATOMIC " } ,
{ int ( ImageType : : AtomicInt2DArray ) , " INT_2D_ARRAY_ATOMIC " } ,
{ int ( ImageType : : AtomicInt3D ) , " INT_3D_ATOMIC " } ,
{ int ( ImageType : : UintBuffer ) , " UINT_BUFFER " } ,
{ int ( ImageType : : Uint1D ) , " UINT_1D " } ,
{ int ( ImageType : : Uint1DArray ) , " UINT_1D_ARRAY " } ,
{ int ( ImageType : : Uint2D ) , " UINT_2D " } ,
{ int ( ImageType : : Uint2DArray ) , " UINT_2D_ARRAY " } ,
{ int ( ImageType : : Uint3D ) , " UINT_3D " } ,
{ int ( ImageType : : UintCube ) , " UINT_CUBE " } ,
{ int ( ImageType : : UintCubeArray ) , " UINT_CUBE_ARRAY " } ,
{ int ( ImageType : : AtomicUint2D ) , " UINT_2D_ATOMIC " } ,
{ int ( ImageType : : AtomicUint2DArray ) , " UINT_2D_ARRAY_ATOMIC " } ,
{ int ( ImageType : : AtomicUint3D ) , " UINT_3D_ATOMIC " } ,
{ int ( ImageType : : Shadow2D ) , " SHADOW_2D " } ,
{ int ( ImageType : : Shadow2DArray ) , " SHADOW_2D_ARRAY " } ,
{ int ( ImageType : : ShadowCube ) , " SHADOW_CUBE " } ,
{ int ( ImageType : : ShadowCubeArray ) , " SHADOW_CUBE_ARRAY " } ,
{ int ( ImageType : : Depth2D ) , " DEPTH_2D " } ,
{ int ( ImageType : : Depth2DArray ) , " DEPTH_2D_ARRAY " } ,
{ int ( ImageType : : DepthCube ) , " DEPTH_CUBE " } ,
{ int ( ImageType : : DepthCubeArray ) , " DEPTH_CUBE_ARRAY " } ,
2022-04-12 18:28:27 -03:00
{ 0 , nullptr } ,
} ;
2023-06-03 08:36:28 +10:00
static const PyC_StringEnumItems pygpu_dualblend_items [ ] = {
2022-09-25 18:33:28 +10:00
{ int ( DualBlend : : NONE ) , " NONE " } ,
{ int ( DualBlend : : SRC_0 ) , " SRC_0 " } ,
{ int ( DualBlend : : SRC_1 ) , " SRC_1 " } ,
2022-04-12 18:28:27 -03:00
{ 0 , nullptr } ,
} ;
2025-03-31 12:37:56 +02:00
static const PyC_StringEnumItems pygpu_depth_write_items [ ] = {
{ int ( DepthWrite : : UNCHANGED ) , " UNCHANGED " } ,
{ int ( DepthWrite : : ANY ) , " ANY " } ,
{ int ( DepthWrite : : GREATER ) , " GREATER " } ,
{ int ( DepthWrite : : LESS ) , " LESS " } ,
{ 0 , nullptr } ,
} ;
2023-11-23 14:23:26 +01:00
# define PYDOC_TEX_FORMAT_ITEMS \
" - ``RGBA8UI`` \n " \
" - ``RGBA8I`` \n " \
" - ``RGBA8`` \n " \
" - ``RGBA32UI`` \n " \
" - ``RGBA32I`` \n " \
" - ``RGBA32F`` \n " \
" - ``RGBA16UI`` \n " \
" - ``RGBA16I`` \n " \
" - ``RGBA16F`` \n " \
" - ``RGBA16`` \n " \
" - ``RG8UI`` \n " \
" - ``RG8I`` \n " \
" - ``RG8`` \n " \
" - ``RG32UI`` \n " \
" - ``RG32I`` \n " \
" - ``RG32F`` \n " \
" - ``RG16UI`` \n " \
" - ``RG16I`` \n " \
" - ``RG16F`` \n " \
" - ``RG16`` \n " \
" - ``R8UI`` \n " \
" - ``R8I`` \n " \
" - ``R8`` \n " \
" - ``R32UI`` \n " \
" - ``R32I`` \n " \
" - ``R32F`` \n " \
" - ``R16UI`` \n " \
" - ``R16I`` \n " \
" - ``R16F`` \n " \
" - ``R16`` \n " \
" - ``R11F_G11F_B10F`` \n " \
" - ``DEPTH32F_STENCIL8`` \n " \
" - ``DEPTH24_STENCIL8`` \n " \
" - ``SRGB8_A8`` \n " \
" - ``RGB16F`` \n " \
" - ``SRGB8_A8_DXT1`` \n " \
" - ``SRGB8_A8_DXT3`` \n " \
" - ``SRGB8_A8_DXT5`` \n " \
" - ``RGBA8_DXT1`` \n " \
" - ``RGBA8_DXT3`` \n " \
" - ``RGBA8_DXT5`` \n " \
" - ``DEPTH_COMPONENT32F`` \n " \
" - ``DEPTH_COMPONENT24`` \n " \
" - ``DEPTH_COMPONENT16`` \n "
extern const PyC_StringEnumItems pygpu_tex_format_items [ ] ;
2022-04-12 18:28:27 -03:00
/* -------------------------------------------------------------------- */
/** \name GPUStageInterfaceInfo Methods
* \ { */
static bool pygpu_interface_info_get_args ( BPyGPUStageInterfaceInfo * self ,
PyObject * args ,
const char * format ,
Type * r_type ,
const char * * r_name )
{
2023-06-03 08:36:28 +10:00
PyC_StringEnum pygpu_type = { pygpu_attrtype_items } ;
2022-04-12 18:28:27 -03:00
PyObject * py_name ;
if ( ! PyArg_ParseTuple ( args , format , PyC_ParseStringEnum , & pygpu_type , & py_name ) ) {
return false ;
}
const char * name = PyUnicode_AsUTF8 ( py_name ) ;
if ( name = = nullptr ) {
return false ;
}
# ifdef USE_GPU_PY_REFERENCES
2025-01-26 20:08:04 +01:00
PyList_Append ( self - > references , py_name ) ;
2022-04-12 18:28:27 -03:00
# endif
* r_type = ( Type ) pygpu_type . value_found ;
* r_name = name ;
return true ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_interface_info_smooth_doc ,
" .. method:: smooth(type, name) \n "
" \n "
2024-11-03 19:18:34 +11:00
" Add an attribute with qualifier of type *smooth* to the interface block. \n "
2024-01-25 10:22:16 +11:00
" \n "
" :arg type: One of these types: \n "
" \n " PYDOC_TYPE_LIST
" \n "
" :type type: str \n "
" :arg name: name of the attribute. \n "
" :type name: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_interface_info_smooth ( BPyGPUStageInterfaceInfo * self , PyObject * args )
{
Type type ;
const char * name ;
if ( ! pygpu_interface_info_get_args ( self , args , " O&O:smooth " , & type , & name ) ) {
return nullptr ;
}
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( self - > interface ) ;
interface - > smooth ( type , name ) ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_interface_info_flat_doc ,
" .. method:: flat(type, name) \n "
" \n "
2024-11-03 19:18:34 +11:00
" Add an attribute with qualifier of type ``flat`` to the interface block. \n "
2024-01-25 10:22:16 +11:00
" \n "
" :arg type: One of these types: \n "
" \n " PYDOC_TYPE_LIST
" \n "
" :type type: str \n "
" :arg name: name of the attribute. \n "
" :type name: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_interface_info_flat ( BPyGPUStageInterfaceInfo * self , PyObject * args )
{
Type type ;
const char * name ;
if ( ! pygpu_interface_info_get_args ( self , args , " O&O:flat " , & type , & name ) ) {
return nullptr ;
}
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( self - > interface ) ;
interface - > flat ( type , name ) ;
Py_RETURN_NONE ;
}
PyDoc_STRVAR (
2024-01-25 10:22:16 +11:00
/* Wrap. */
2022-04-12 18:28:27 -03:00
pygpu_interface_info_no_perspective_doc ,
" .. method:: no_perspective(type, name) \n "
" \n "
2024-11-03 19:18:34 +11:00
" Add an attribute with qualifier of type ``no_perspective`` to the interface block. \n "
2022-04-12 18:28:27 -03:00
" \n "
2022-09-19 14:22:31 +10:00
" :arg type: One of these types: \n "
2022-04-12 18:28:27 -03:00
" \n " PYDOC_TYPE_LIST
2022-04-13 22:38:16 +10:00
" \n "
2022-04-12 18:28:27 -03:00
" :type type: str \n "
2022-09-19 14:22:31 +10:00
" :arg name: name of the attribute. \n "
2022-04-12 18:28:27 -03:00
" :type name: str \n " ) ;
static PyObject * pygpu_interface_info_no_perspective ( BPyGPUStageInterfaceInfo * self ,
PyObject * args )
{
Type type ;
const char * name ;
if ( ! pygpu_interface_info_get_args ( self , args , " O&O:no_perspective " , & type , & name ) ) {
return nullptr ;
}
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( self - > interface ) ;
interface - > no_perspective ( type , name ) ;
Py_RETURN_NONE ;
}
2023-06-03 08:36:28 +10:00
static PyMethodDef pygpu_interface_info__tp_methods [ ] = {
2022-04-12 18:28:27 -03:00
{ " smooth " ,
( PyCFunction ) pygpu_interface_info_smooth ,
METH_VARARGS ,
pygpu_interface_info_smooth_doc } ,
{ " flat " , ( PyCFunction ) pygpu_interface_info_flat , METH_VARARGS , pygpu_interface_info_flat_doc } ,
{ " no_perspective " ,
( PyCFunction ) pygpu_interface_info_no_perspective ,
METH_VARARGS ,
pygpu_interface_info_no_perspective_doc } ,
{ nullptr , nullptr , 0 , nullptr } ,
} ;
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPUStageInterfaceInfo Getters and Setters
* \ { */
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_interface_info_name_doc ,
" Name of the interface block. \n "
" \n "
" :type: str " ) ;
2022-10-03 17:37:25 -05:00
static PyObject * pygpu_interface_info_name_get ( BPyGPUStageInterfaceInfo * self , void * /*closure*/ )
2022-04-12 18:28:27 -03:00
{
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( self - > interface ) ;
2025-04-01 12:33:56 +11:00
return PyC_UnicodeFromStdStr ( interface - > name ) ;
2022-04-12 18:28:27 -03:00
}
static PyGetSetDef pygpu_interface_info__tp_getseters [ ] = {
{ " name " ,
( getter ) pygpu_interface_info_name_get ,
( setter ) nullptr ,
pygpu_interface_info_name_doc ,
nullptr } ,
{ nullptr , nullptr , nullptr , nullptr , nullptr } /* Sentinel */
} ;
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPUStageInterfaceInfo Type
* \ { */
2022-10-03 17:37:25 -05:00
static PyObject * pygpu_interface_info__tp_new ( PyTypeObject * /*type*/ ,
2022-04-12 18:28:27 -03:00
PyObject * args ,
PyObject * kwds )
{
if ( kwds ) {
PyErr_SetString ( PyExc_TypeError , " no keywords are expected " ) ;
return nullptr ;
}
const char * name ;
if ( ! PyArg_ParseTuple ( args , " s:GPUStageInterfaceInfo.__new__* " , & name ) ) {
return nullptr ;
}
StageInterfaceInfo * interface = new StageInterfaceInfo ( name , " " ) ;
GPUStageInterfaceInfo * interface_info = reinterpret_cast < GPUStageInterfaceInfo * > ( interface ) ;
2023-09-08 16:53:27 +10:00
PyObject * self = BPyGPUStageInterfaceInfo_CreatePyObject ( interface_info ) ;
2022-04-12 18:28:27 -03:00
# ifdef USE_GPU_PY_REFERENCES
PyObject * py_name = PyTuple_GET_ITEM ( args , 0 ) ;
PyList_Append ( ( ( BPyGPUStageInterfaceInfo * ) self ) - > references , py_name ) ;
# endif
return self ;
}
# ifdef USE_GPU_PY_REFERENCES
static int pygpu_interface_info__tp_traverse ( PyObject * self , visitproc visit , void * arg )
{
BPyGPUStageInterfaceInfo * py_interface = reinterpret_cast < BPyGPUStageInterfaceInfo * > ( self ) ;
Py_VISIT ( py_interface - > references ) ;
return 0 ;
}
static int pygpu_interface_info__tp_clear ( PyObject * self )
{
BPyGPUStageInterfaceInfo * py_interface = reinterpret_cast < BPyGPUStageInterfaceInfo * > ( self ) ;
Py_CLEAR ( py_interface - > references ) ;
return 0 ;
}
# endif
static void pygpu_interface_info__tp_dealloc ( PyObject * self )
{
BPyGPUStageInterfaceInfo * py_interface = reinterpret_cast < BPyGPUStageInterfaceInfo * > ( self ) ;
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( py_interface - > interface ) ;
delete interface ;
# ifdef USE_GPU_PY_REFERENCES
PyObject_GC_UnTrack ( self ) ;
if ( py_interface - > references ) {
pygpu_interface_info__tp_clear ( self ) ;
Py_CLEAR ( py_interface - > references ) ;
}
# endif
2025-01-26 20:08:04 +01:00
Py_TYPE ( self ) - > tp_free ( self ) ;
2022-04-12 18:28:27 -03:00
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_interface_info__tp_doc ,
" .. class:: GPUStageInterfaceInfo(name) \n "
" \n "
" List of varyings between shader stages. \n "
" \n "
" :arg name: Name of the interface block. \n "
" :type value: str \n " ) ;
2023-07-16 17:43:31 +10:00
PyTypeObject BPyGPUStageInterfaceInfo_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT ( nullptr , 0 )
/*tp_name*/ " GPUStageInterfaceInfo " ,
/*tp_basicsize*/ sizeof ( BPyGPUStageInterfaceInfo ) ,
/*tp_itemsize*/ 0 ,
/*tp_dealloc*/ pygpu_interface_info__tp_dealloc ,
/*tp_vectorcall_offset*/ 0 ,
/*tp_getattr*/ nullptr ,
/*tp_setattr*/ nullptr ,
/*tp_compare*/ nullptr ,
/*tp_repr*/ nullptr ,
/*tp_as_number*/ nullptr ,
/*tp_as_sequence*/ nullptr ,
/*tp_as_mapping*/ nullptr ,
/*tp_hash*/ nullptr ,
/*tp_call*/ nullptr ,
/*tp_str*/ nullptr ,
/*tp_getattro*/ nullptr ,
/*tp_setattro*/ nullptr ,
/*tp_as_buffer*/ nullptr ,
2022-04-12 18:28:27 -03:00
# ifdef USE_GPU_PY_REFERENCES
2023-07-16 17:43:31 +10:00
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,
2022-04-12 18:28:27 -03:00
# else
2023-07-16 17:43:31 +10:00
/*tp_flags*/ Py_TPFLAGS_DEFAULT ,
2022-04-12 18:28:27 -03:00
# endif
2023-07-16 17:43:31 +10:00
/*tp_doc*/ pygpu_interface_info__tp_doc ,
# ifdef USE_GPU_PY_REFERENCES
/*tp_traverse*/ pygpu_interface_info__tp_traverse ,
# else
/*tp_traverse*/ nullptr ,
# endif
# ifdef USE_GPU_PY_REFERENCES
/*tp_clear*/ pygpu_interface_info__tp_clear ,
# else
/*tp_clear*/ nullptr ,
# endif
/*tp_richcompare*/ nullptr ,
/*tp_weaklistoffset*/ 0 ,
/*tp_iter*/ nullptr ,
/*tp_iternext*/ nullptr ,
/*tp_methods*/ pygpu_interface_info__tp_methods ,
/*tp_members*/ nullptr ,
/*tp_getset*/ pygpu_interface_info__tp_getseters ,
/*tp_base*/ nullptr ,
/*tp_dict*/ nullptr ,
/*tp_descr_get*/ nullptr ,
/*tp_descr_set*/ nullptr ,
/*tp_dictoffset*/ 0 ,
/*tp_init*/ nullptr ,
/*tp_alloc*/ nullptr ,
/*tp_new*/ pygpu_interface_info__tp_new ,
/*tp_free*/ nullptr ,
/*tp_is_gc*/ nullptr ,
/*tp_bases*/ nullptr ,
/*tp_mro*/ nullptr ,
/*tp_cache*/ nullptr ,
/*tp_subclasses*/ nullptr ,
/*tp_weaklist*/ nullptr ,
/*tp_del*/ nullptr ,
/*tp_version_tag*/ 0 ,
/*tp_finalize*/ nullptr ,
/*tp_vectorcall*/ nullptr ,
} ;
2022-04-12 18:28:27 -03:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name GPUShaderCreateInfo Methods
* \ { */
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_vertex_in_doc ,
" .. method:: vertex_in(slot, type, name) \n "
" \n "
" Add a vertex shader input attribute. \n "
" \n "
" :arg slot: The attribute index. \n "
" :type slot: int \n "
" :arg type: One of these types: \n "
" \n " PYDOC_TYPE_LIST
" \n "
" :type type: str \n "
" :arg name: name of the attribute. \n "
" :type name: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_vertex_in ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
int slot ;
2023-06-03 08:36:28 +10:00
PyC_StringEnum pygpu_type = { pygpu_attrtype_items } ;
2022-04-12 18:28:27 -03:00
const char * param ;
if ( ! PyArg_ParseTuple ( args , " iO&s:vertex_in " , & slot , PyC_ParseStringEnum , & pygpu_type , & param ) ) {
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyObject * py_name = PyTuple_GET_ITEM ( args , 2 ) ;
PyList_Append ( self - > references , py_name ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > vertex_in ( slot , ( Type ) pygpu_type . value_found , param ) ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_vertex_out_doc ,
" .. method:: vertex_out(interface) \n "
" \n "
" Add a vertex shader output interface block. \n "
" \n "
" :arg interface: Object describing the block. \n "
" :type interface: :class:`gpu.types.GPUStageInterfaceInfo` \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_vertex_out ( BPyGPUShaderCreateInfo * self ,
BPyGPUStageInterfaceInfo * o )
{
if ( ! BPyGPUStageInterfaceInfo_Check ( o ) ) {
PyErr_Format ( PyExc_TypeError , " Expected a GPUStageInterfaceInfo, got %s " , Py_TYPE ( o ) - > tp_name ) ;
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyList_Append ( self - > references , ( PyObject * ) o ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
StageInterfaceInfo * interface = reinterpret_cast < StageInterfaceInfo * > ( o - > interface ) ;
info - > vertex_out ( * interface ) ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_fragment_out_doc ,
" .. method:: fragment_out(slot, type, name, blend='NONE') \n "
" \n "
" Specify a fragment output corresponding to a framebuffer target slot. \n "
" \n "
" :arg slot: The attribute index. \n "
" :type slot: int \n "
" :arg type: One of these types: \n "
" \n " PYDOC_TYPE_LIST
" \n "
" :type type: str \n "
" :arg name: Name of the attribute. \n "
" :type name: str \n "
" :arg blend: Dual Source Blending Index. It can be 'NONE', 'SRC_0' or 'SRC_1'. \n "
" :type blend: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_fragment_out ( BPyGPUShaderCreateInfo * self ,
PyObject * args ,
PyObject * kwds )
{
int slot ;
2023-06-03 08:36:28 +10:00
PyC_StringEnum pygpu_type = { pygpu_attrtype_items } ;
2022-04-12 18:28:27 -03:00
const char * name ;
2023-06-03 08:36:28 +10:00
PyC_StringEnum blend_type = { pygpu_dualblend_items , int ( DualBlend : : NONE ) } ;
2022-04-12 18:28:27 -03:00
static const char * _keywords [ ] = { " slot " , " type " , " name " , " blend " , nullptr } ;
2022-04-14 11:21:51 +10:00
static _PyArg_Parser _parser = {
2023-08-30 14:05:32 +10:00
PY_ARG_PARSER_HEAD_COMPAT ( )
2022-04-14 11:21:51 +10:00
" i " /* `slot` */
" O& " /* `type` */
" s " /* `name` */
" |$ " /* Optional keyword only arguments. */
" O& " /* `blend` */
" :fragment_out " ,
_keywords ,
nullptr ,
} ;
2022-04-12 18:28:27 -03:00
if ( ! _PyArg_ParseTupleAndKeywordsFast ( args ,
kwds ,
& _parser ,
& slot ,
PyC_ParseStringEnum ,
& pygpu_type ,
& name ,
PyC_ParseStringEnum ,
& blend_type ) )
{
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyObject * py_name = PyTuple_GET_ITEM ( args , 2 ) ;
PyList_Append ( self - > references , py_name ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > fragment_out ( slot , ( Type ) pygpu_type . value_found , name , ( DualBlend ) blend_type . value_found ) ;
Py_RETURN_NONE ;
}
2025-03-31 12:37:56 +02:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_depth_write_doc ,
" .. method:: depth_write(value) \n "
" \n "
" Specify a depth write behavior when modifying gl_FragDepth. \n "
" \n "
" There is a common optimization for GPUs that relies on an early depth \n "
" test to be run before the fragment shader so that the shader evaluation \n "
" can be skipped if the fragment ends up being discarded because it is occluded. \n "
" \n "
" This optimization does not affect the final rendering, and is typically \n "
" possible when the fragment does not change the depth programmatically. \n "
" There are, however a class of operations on the depth in the shader which \n "
" could still be performed while allowing the early depth test to operate. \n "
" \n "
" This function alters the behavior of the optimization to allow those operations \n "
" to be performed. \n "
" \n "
2025-04-04 10:17:02 +11:00
" :arg value: Depth write value. "
" It can be 'UNCHANGED' (default), 'ANY', 'GREATER' or 'LESS'. \n "
" :UNCHANGED: disables depth write in a fragment shader and execution of the "
" fragments can be optimized away. \n "
" :ANY: enables depth write in a fragment shader for any fragments \n "
" :GREATER: enables depth write in a fragment shader for depth values that "
" are greater than the depth value in the output buffer. \n "
" :LESS: enables depth write in a fragment shader for depth values that "
" are less than the depth value in the output buffer. \n "
2025-03-31 12:37:56 +02:00
" :type blend: str \n " ) ;
static PyObject * pygpu_shader_info_depth_write ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
PyC_StringEnum depth_write = { pygpu_depth_write_items , int ( DepthWrite : : UNCHANGED ) } ;
if ( ! PyC_ParseStringEnum ( args , & depth_write ) ) {
return nullptr ;
}
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > depth_write ( DepthWrite ( depth_write . value_found ) ) ;
Py_RETURN_NONE ;
}
2022-04-12 18:28:27 -03:00
PyDoc_STRVAR (
2024-01-25 10:22:16 +11:00
/* Wrap. */
2022-04-12 18:28:27 -03:00
pygpu_shader_info_uniform_buf_doc ,
" .. method:: uniform_buf(slot, type_name, name) \n "
" \n "
2024-11-03 19:18:34 +11:00
" Specify a uniform variable whose type can be one of those declared in "
" :meth:`gpu.types.GPUShaderCreateInfo.typedef_source`. \n "
2022-04-12 18:28:27 -03:00
" \n "
2022-09-19 14:22:31 +10:00
" :arg slot: The uniform variable index. \n "
2022-04-12 18:28:27 -03:00
" :type slot: int \n "
2024-11-03 19:18:34 +11:00
" :arg type_name: Name of the data type. "
" It can be a struct type defined in the source passed through the "
" :meth:`gpu.types.GPUShaderCreateInfo.typedef_source`. \n "
2022-04-12 18:28:27 -03:00
" :type type_name: str \n "
2022-09-19 14:22:31 +10:00
" :arg name: The uniform variable name. \n "
2022-04-12 18:28:27 -03:00
" :type name: str \n " ) ;
static PyObject * pygpu_shader_info_uniform_buf ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
int slot ;
const char * type_name ;
const char * name ;
if ( ! PyArg_ParseTuple ( args , " iss:uniform_buf " , & slot , & type_name , & name ) ) {
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 1 ) ) ; /* type_name */
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 2 ) ) ; /* name */
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > uniform_buf ( slot , type_name , name ) ;
Py_RETURN_NONE ;
}
# ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
PyDoc_STRVAR (
2024-01-25 10:22:16 +11:00
/* Wrap. */
2022-04-12 18:28:27 -03:00
pygpu_shader_info_image_doc ,
" .. method:: image(slot, format, type, name, qualifiers={'NO_RESTRICT'}) \n "
" \n "
" Specify an image resource used for arbitrary load and store operations. \n "
" \n "
2022-09-19 14:22:31 +10:00
" :arg slot: The image resource index. \n "
2022-04-12 18:28:27 -03:00
" :type slot: int \n "
2022-09-19 14:22:31 +10:00
" :arg format: The GPUTexture format that is passed to the shader. Possible values are: \n "
2023-11-23 14:23:26 +01:00
" \n " PYDOC_TEX_FORMAT_ITEMS
2022-04-12 18:28:27 -03:00
" :type format: str \n "
2022-09-19 14:22:31 +10:00
" :arg type: The data type describing how the image is to be read in the shader. "
2022-04-12 18:28:27 -03:00
" Possible values are: \n "
2022-04-13 22:38:16 +10:00
" \n " PYDOC_IMAGE_TYPES
" \n "
2022-04-12 18:28:27 -03:00
" :type type: str \n "
2022-09-19 14:22:31 +10:00
" :arg name: The image resource name. \n "
2022-04-12 18:28:27 -03:00
" :type name: str \n "
2022-09-19 14:22:31 +10:00
" :arg qualifiers: Set containing values that describe how the image resource is to be "
2022-04-12 18:28:27 -03:00
" read or written. Possible values are: \n "
" " PYDOC_QUALIFIERS
" "
2024-11-03 15:42:19 +11:00
" :type qualifiers: set[str] \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_image ( BPyGPUShaderCreateInfo * self ,
PyObject * args ,
PyObject * kwds )
{
int slot ;
2023-12-17 16:24:36 +11:00
PyC_StringEnum pygpu_texformat = { pygpu_textureformat_items } ;
PyC_StringEnum pygpu_imagetype = { pygpu_imagetype_items } ;
2022-04-12 18:28:27 -03:00
const char * name ;
PyObject * py_qualifiers = nullptr ;
2025-04-24 14:38:13 +02:00
Qualifier qualifier = Qualifier : : no_restrict ;
2022-04-12 18:28:27 -03:00
static const char * _keywords [ ] = { " slot " , " format " , " type " , " name " , " qualifiers " , nullptr } ;
2022-04-14 11:21:51 +10:00
static _PyArg_Parser _parser = {
2023-08-30 14:05:32 +10:00
PY_ARG_PARSER_HEAD_COMPAT ( )
2022-04-14 11:21:51 +10:00
" i " /* `slot` */
" O& " /* `format` */
" O& " /* `type` */
" s " /* `name` */
" |$ " /* Optional keyword only arguments. */
" O " /* `qualifiers` */
" :image " ,
_keywords ,
nullptr ,
} ;
2022-04-12 18:28:27 -03:00
if ( ! _PyArg_ParseTupleAndKeywordsFast ( args ,
kwds ,
& _parser ,
& slot ,
PyC_ParseStringEnum ,
& pygpu_texformat ,
PyC_ParseStringEnum ,
& pygpu_imagetype ,
& name ,
& py_qualifiers ) )
{
return nullptr ;
}
if ( py_qualifiers & &
PyC_FlagSet_ToBitfield (
pygpu_qualifiers , py_qualifiers , ( int * ) & qualifier , " shader_info.image " ) = = - 1 )
{
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 3 ) ) ; /* name */
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > image ( slot ,
( eGPUTextureFormat ) pygpu_texformat . value_found ,
qualifier ,
2025-04-24 14:38:13 +02:00
blender : : gpu : : shader : : ImageReadWriteType ( pygpu_imagetype . value_found ) ,
2022-04-12 18:28:27 -03:00
name ) ;
Py_RETURN_NONE ;
}
# endif
PyDoc_STRVAR (
2024-01-25 10:22:16 +11:00
/* Wrap. */
2022-04-12 18:28:27 -03:00
pygpu_shader_info_sampler_doc ,
" .. method:: sampler(slot, type, name) \n "
" \n "
" Specify an image texture sampler. \n "
" \n "
2022-09-19 14:22:31 +10:00
" :arg slot: The image texture sampler index. \n "
2022-04-12 18:28:27 -03:00
" :type slot: int \n "
2022-09-19 14:22:31 +10:00
" :arg type: The data type describing the format of each sampler unit. Possible values "
2022-04-12 18:28:27 -03:00
" are: \n "
2022-04-13 22:38:16 +10:00
" \n " PYDOC_IMAGE_TYPES
" \n "
2022-04-12 18:28:27 -03:00
" :type type: str \n "
2022-09-19 14:22:31 +10:00
" :arg name: The image texture sampler name. \n "
2022-04-12 18:28:27 -03:00
" :type name: str \n " ) ;
static PyObject * pygpu_shader_info_sampler ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
int slot ;
2023-06-03 08:36:28 +10:00
PyC_StringEnum pygpu_samplertype = { pygpu_imagetype_items } ;
2022-04-12 18:28:27 -03:00
const char * name ;
if ( ! PyArg_ParseTuple (
2024-01-02 18:12:54 +01:00
args , " iO&s:sampler " , & slot , PyC_ParseStringEnum , & pygpu_samplertype , & name ) )
{
2022-04-12 18:28:27 -03:00
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 2 ) ) ; /* name */
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > sampler ( slot , ( ImageType ) pygpu_samplertype . value_found , name ) ;
Py_RETURN_NONE ;
}
static int constant_type_size ( Type type )
{
switch ( type ) {
2025-04-11 22:39:01 +02:00
case Type : : bool_t :
case Type : : float_t :
case Type : : int_t :
case Type : : uint_t :
case Type : : uchar4_t :
case Type : : char4_t :
case Type : : float3_10_10_10_2_t :
case Type : : ushort2_t :
case Type : : short2_t :
2022-04-12 18:28:27 -03:00
return 4 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : ushort3_t :
case Type : : short3_t :
2023-09-04 18:45:40 +02:00
return 6 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : float2_t :
case Type : : uint2_t :
case Type : : int2_t :
case Type : : ushort4_t :
case Type : : short4_t :
2022-04-12 18:28:27 -03:00
return 8 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : float3_t :
case Type : : uint3_t :
case Type : : int3_t :
2022-04-12 18:28:27 -03:00
return 12 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : float4_t :
case Type : : uint4_t :
case Type : : int4_t :
2022-04-12 18:28:27 -03:00
return 16 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : float3x3_t :
2022-04-12 22:31:27 -03:00
return 36 + 3 * 4 ;
2025-04-11 22:39:01 +02:00
case Type : : float4x4_t :
2022-04-12 22:31:27 -03:00
return 64 ;
2022-04-12 18:28:27 -03:00
break ;
2025-04-11 22:39:01 +02:00
case Type : : uchar_t :
case Type : : char_t :
2022-09-01 22:22:32 +02:00
return 1 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : uchar2_t :
case Type : : char2_t :
case Type : : ushort_t :
case Type : : short_t :
2022-09-01 22:22:32 +02:00
return 2 ;
break ;
2025-04-11 22:39:01 +02:00
case Type : : uchar3_t :
case Type : : char3_t :
2022-09-01 22:22:32 +02:00
return 3 ;
break ;
2022-04-12 18:28:27 -03:00
}
BLI_assert ( false ) ;
return - 1 ;
}
static int constants_calc_size ( ShaderCreateInfo * info )
{
int size_prev = 0 ;
int size_last = 0 ;
for ( const ShaderCreateInfo : : PushConst & uniform : info - > push_constants_ ) {
int pad = 0 ;
int size = constant_type_size ( uniform . type ) ;
if ( size_last & & size_last ! = size ) {
/* Calc pad. */
int pack = ( size = = 8 ) ? 8 : 16 ;
if ( size_last < size ) {
pad = pack - ( size_last % pack ) ;
}
else {
pad = size_prev % pack ;
}
}
else if ( size = = 12 ) {
/* It is still unclear how Vulkan handles padding for `vec3` constants. For now let's follow
* the rules of the ` std140 ` layout . */
pad = 4 ;
}
size_prev + = pad + size * std : : max ( 1 , uniform . array_size ) ;
size_last = size ;
}
return size_prev + ( size_prev % 16 ) ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_push_constant_doc ,
" .. method:: push_constant(type, name, size=0) \n "
" \n "
" Specify a global access constant. \n "
" \n "
" :arg type: One of these types: \n "
" \n " PYDOC_TYPE_LIST
" \n "
" :type type: str \n "
" :arg name: Name of the constant. \n "
" :type name: str \n "
2024-11-03 15:42:19 +11:00
" :arg size: If not zero, indicates that the constant is an array with the specified size. \n "
" :type size: int \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_push_constant ( BPyGPUShaderCreateInfo * self ,
PyObject * args ,
PyObject * kwds )
{
2023-06-03 08:36:28 +10:00
PyC_StringEnum pygpu_type = { pygpu_attrtype_items } ;
2022-04-12 18:28:27 -03:00
const char * name = nullptr ;
int array_size = 0 ;
static const char * _keywords [ ] = { " type " , " name " , " size " , nullptr } ;
2022-04-14 11:21:51 +10:00
static _PyArg_Parser _parser = {
2023-08-30 14:05:32 +10:00
PY_ARG_PARSER_HEAD_COMPAT ( )
2022-04-14 11:21:51 +10:00
" O& " /* `type` */
" s " /* `name` */
" | " /* Optional arguments. */
" I " /* `size` */
" :push_constant " ,
_keywords ,
nullptr ,
} ;
2022-04-12 18:28:27 -03:00
if ( ! _PyArg_ParseTupleAndKeywordsFast (
args , kwds , & _parser , PyC_ParseStringEnum , & pygpu_type , & name , & array_size ) )
{
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyObject * py_name = PyTuple_GET_ITEM ( args , 1 ) ;
PyList_Append ( self - > references , py_name ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > push_constant ( ( Type ) pygpu_type . value_found , name , array_size ) ;
# define VULKAN_LIMIT 128
int size = constants_calc_size ( info ) ;
if ( size > VULKAN_LIMIT ) {
2023-05-09 12:50:37 +10:00
printf ( " Push constants have a minimum supported size of " STRINGIFY ( VULKAN_LIMIT ) " bytes, however the constants added so far already reach %d bytes. Consider using UBO. \n " , size ) ;
2022-04-12 18:28:27 -03:00
}
# undef VULKAN_LIMIT
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_vertex_source_doc ,
" .. method:: vertex_source(source) \n "
" \n "
" Vertex shader source code written in GLSL. \n "
" \n "
" Example: \n "
" \n "
" .. code-block:: python \n "
" \n "
" \" void main {gl_Position = vec4(pos, 1.0);} \" \n "
" \n "
" :arg source: The vertex shader source code. \n "
" :type source: str \n "
" \n "
" .. seealso:: `GLSL Cross Compilation "
" <https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__ \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_vertex_source ( BPyGPUShaderCreateInfo * self , PyObject * o )
{
const char * vertex_source = PyUnicode_AsUTF8 ( o ) ;
if ( vertex_source = = nullptr ) {
PyErr_Format ( PyExc_ValueError , " expected a string, got %s " , Py_TYPE ( o ) - > tp_name ) ;
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
if ( self - > vertex_source ) {
Py_DECREF ( self - > vertex_source ) ;
}
self - > vertex_source = o ;
Py_INCREF ( o ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
2025-04-16 20:19:09 +02:00
info - > vertex_source ( " draw_colormanagement_lib.glsl " ) ;
2022-04-12 18:28:27 -03:00
info - > vertex_source_generated = vertex_source ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_compute_source_doc ,
" .. method:: compute_source(source) \n "
" \n "
" compute shader source code written in GLSL. \n "
" \n "
" Example: \n "
" \n "
" .. code-block:: python \n "
" \n "
" \" \" \" void main() { \n "
" int2 index = int2(gl_GlobalInvocationID.xy); \n "
" vec4 color = vec4(0.0, 0.0, 0.0, 1.0); \n "
" imageStore(img_output, index, color); \n "
" } \" \" \" \n "
" \n "
" :arg source: The compute shader source code. \n "
" :type source: str \n "
" \n "
" .. seealso:: `GLSL Cross Compilation "
" <https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__ \n " ) ;
2023-11-23 14:23:26 +01:00
static PyObject * pygpu_shader_info_compute_source ( BPyGPUShaderCreateInfo * self , PyObject * o )
{
const char * compute_source = PyUnicode_AsUTF8 ( o ) ;
if ( compute_source = = nullptr ) {
PyErr_Format ( PyExc_ValueError , " expected a string, got %s " , Py_TYPE ( o ) - > tp_name ) ;
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
if ( self - > compute_source ) {
Py_DECREF ( self - > compute_source ) ;
}
self - > compute_source = o ;
Py_INCREF ( o ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
2025-04-16 20:19:09 +02:00
info - > compute_source ( " draw_colormanagement_lib.glsl " ) ;
2023-11-23 14:23:26 +01:00
info - > compute_source_generated = compute_source ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_fragment_source_doc ,
" .. method:: fragment_source(source) \n "
" \n "
" Fragment shader source code written in GLSL. \n "
" \n "
" Example: \n "
" \n "
" .. code-block:: python \n "
" \n "
" \" void main {fragColor = vec4(0.0, 0.0, 0.0, 1.0);} \" \n "
" \n "
" :arg source: The fragment shader source code. \n "
" :type source: str \n "
" \n "
" .. seealso:: `GLSL Cross Compilation "
" <https://developer.blender.org/docs/features/gpu/glsl_cross_compilation/>`__ \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_fragment_source ( BPyGPUShaderCreateInfo * self , PyObject * o )
{
const char * fragment_source = PyUnicode_AsUTF8 ( o ) ;
if ( fragment_source = = nullptr ) {
PyErr_Format ( PyExc_ValueError , " expected a string, got %s " , Py_TYPE ( o ) - > tp_name ) ;
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
if ( self - > fragment_source ) {
Py_DECREF ( self - > fragment_source ) ;
}
self - > fragment_source = o ;
Py_INCREF ( o ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
2025-04-16 20:19:09 +02:00
info - > fragment_source ( " draw_colormanagement_lib.glsl " ) ;
2022-04-12 18:28:27 -03:00
info - > fragment_source_generated = fragment_source ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_typedef_source_doc ,
" .. method:: typedef_source(source) \n "
" \n "
" Source code included before resource declaration. "
" Useful for defining structs used by Uniform Buffers. \n "
" \n "
" Example: \n "
" \n "
" .. code-block:: python \n "
" \n "
" \" struct MyType {int foo; float bar;}; \" \n "
" \n "
" :arg source: The source code defining types. \n "
" :type source: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_typedef_source ( BPyGPUShaderCreateInfo * self , PyObject * o )
{
const char * typedef_source = PyUnicode_AsUTF8 ( o ) ;
if ( typedef_source = = nullptr ) {
PyErr_Format ( PyExc_ValueError , " expected a string, got %s " , Py_TYPE ( o ) - > tp_name ) ;
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
if ( self - > typedef_source ) {
Py_DECREF ( self - > typedef_source ) ;
}
self - > typedef_source = o ;
Py_INCREF ( o ) ;
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
#if 0
if ( info - > typedef_sources_ . is_empty ( ) ) {
2024-03-23 01:24:18 +01:00
info - > typedef_source ( " GPU_shader_shared_utils.hh " ) ;
2022-04-12 18:28:27 -03:00
}
# endif
info - > typedef_source_generated = typedef_source ;
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_define_doc ,
" .. method:: define(name, value) \n "
" \n "
" Add a preprocessing define directive. In GLSL it would be something like: \n "
" \n "
" .. code-block:: glsl \n "
" \n "
" #define name value \n "
" \n "
" :arg name: Token name. \n "
" :type name: str \n "
" :arg value: Text that replaces token occurrences. \n "
" :type value: str \n " ) ;
2022-04-12 18:28:27 -03:00
static PyObject * pygpu_shader_info_define ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
const char * name ;
const char * value = nullptr ;
if ( ! PyArg_ParseTuple ( args , " s|s:define " , & name , & value ) ) {
return nullptr ;
}
# ifdef USE_GPU_PY_REFERENCES
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 0 ) ) ; /* name */
if ( value ) {
PyList_Append ( self - > references , PyTuple_GET_ITEM ( args , 1 ) ) ; /* value */
}
# endif
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
if ( value ) {
info - > define ( name , value ) ;
}
else {
info - > define ( name ) ;
}
Py_RETURN_NONE ;
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info_local_group_size_doc ,
" .. method:: local_group_size(x, y=-1, z=-1) \n "
" \n "
" Specify the local group size for compute shaders. \n "
" \n "
" :arg x: The local group size in the x dimension. \n "
" :type x: int \n "
" :arg y: The local group size in the y dimension. Optional. Defaults to -1. \n "
" :type y: int \n "
" :arg z: The local group size in the z dimension. Optional. Defaults to -1. \n "
" :type z: int \n " ) ;
2023-11-23 14:23:26 +01:00
static PyObject * pygpu_shader_info_local_group_size ( BPyGPUShaderCreateInfo * self , PyObject * args )
{
int x = - 1 , y = - 1 , z = - 1 ;
if ( ! PyArg_ParseTuple ( args , " i|ii:local_group_size " , & x , & y , & z ) ) {
return nullptr ;
}
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( self - > info ) ;
info - > local_group_size ( x , y , z ) ;
Py_RETURN_NONE ;
}
2023-06-03 08:36:28 +10:00
static PyMethodDef pygpu_shader_info__tp_methods [ ] = {
2022-04-12 18:28:27 -03:00
{ " vertex_in " ,
( PyCFunction ) pygpu_shader_info_vertex_in ,
METH_VARARGS ,
pygpu_shader_info_vertex_in_doc } ,
{ " vertex_out " ,
( PyCFunction ) pygpu_shader_info_vertex_out ,
METH_O ,
pygpu_shader_info_vertex_out_doc } ,
2025-03-31 12:37:56 +02:00
{ " depth_write " ,
( PyCFunction ) ( void * ) pygpu_shader_info_depth_write ,
METH_O ,
pygpu_shader_info_depth_write_doc } ,
2022-04-12 18:28:27 -03:00
{ " fragment_out " ,
( PyCFunction ) ( void * ) pygpu_shader_info_fragment_out ,
METH_VARARGS | METH_KEYWORDS ,
pygpu_shader_info_fragment_out_doc } ,
{ " uniform_buf " ,
( PyCFunction ) ( void * ) pygpu_shader_info_uniform_buf ,
METH_VARARGS ,
pygpu_shader_info_uniform_buf_doc } ,
# ifdef USE_PYGPU_SHADER_INFO_IMAGE_METHOD
{ " image " ,
( PyCFunction ) ( void * ) pygpu_shader_info_image ,
METH_VARARGS | METH_KEYWORDS ,
pygpu_shader_info_image_doc } ,
# endif
{ " sampler " ,
( PyCFunction ) pygpu_shader_info_sampler ,
METH_VARARGS ,
pygpu_shader_info_sampler_doc } ,
{ " push_constant " ,
( PyCFunction ) ( void * ) pygpu_shader_info_push_constant ,
METH_VARARGS | METH_KEYWORDS ,
pygpu_shader_info_push_constant_doc } ,
{ " vertex_source " ,
( PyCFunction ) pygpu_shader_info_vertex_source ,
METH_O ,
pygpu_shader_info_vertex_source_doc } ,
{ " fragment_source " ,
( PyCFunction ) pygpu_shader_info_fragment_source ,
METH_O ,
pygpu_shader_info_fragment_source_doc } ,
2023-11-23 14:23:26 +01:00
{ " compute_source " ,
2023-11-23 15:09:36 -08:00
( PyCFunction ) pygpu_shader_info_compute_source ,
METH_O ,
pygpu_shader_info_compute_source_doc } ,
2022-04-12 18:28:27 -03:00
{ " typedef_source " ,
( PyCFunction ) pygpu_shader_info_typedef_source ,
METH_O ,
pygpu_shader_info_typedef_source_doc } ,
{ " define " , ( PyCFunction ) pygpu_shader_info_define , METH_VARARGS , pygpu_shader_info_define_doc } ,
2023-11-23 14:23:26 +01:00
{ " local_group_size " ,
( PyCFunction ) pygpu_shader_info_local_group_size ,
METH_VARARGS ,
pygpu_shader_info_local_group_size_doc } ,
2022-04-12 18:28:27 -03:00
{ nullptr , nullptr , 0 , nullptr } ,
} ;
/** \} */
/* -------------------------------------------------------------------- */
2022-09-23 14:33:43 +10:00
/** \name GPUShaderCreateInfo Initialization
2022-04-12 18:28:27 -03:00
* \ { */
2022-10-03 17:37:25 -05:00
static PyObject * pygpu_shader_info__tp_new ( PyTypeObject * /*type*/ , PyObject * args , PyObject * kwds )
2022-04-12 18:28:27 -03:00
{
if ( PyTuple_Size ( args ) | | kwds ) {
PyErr_SetString ( PyExc_TypeError , " no args or keywords are expected " ) ;
return nullptr ;
}
ShaderCreateInfo * info = new ShaderCreateInfo ( " pyGPU_Shader " ) ;
GPUShaderCreateInfo * shader_info = reinterpret_cast < GPUShaderCreateInfo * > ( info ) ;
return BPyGPUShaderCreateInfo_CreatePyObject ( shader_info ) ;
}
# ifdef USE_GPU_PY_REFERENCES
static int pygpu_shader_info__tp_traverse ( PyObject * self , visitproc visit , void * arg )
{
BPyGPUShaderCreateInfo * py_info = reinterpret_cast < BPyGPUShaderCreateInfo * > ( self ) ;
Py_VISIT ( py_info - > vertex_source ) ;
Py_VISIT ( py_info - > fragment_source ) ;
2023-11-23 14:23:26 +01:00
Py_VISIT ( py_info - > compute_source ) ;
2022-04-12 18:28:27 -03:00
Py_VISIT ( py_info - > references ) ;
return 0 ;
}
static int pygpu_shader_info__tp_clear ( PyObject * self )
{
BPyGPUShaderCreateInfo * py_info = reinterpret_cast < BPyGPUShaderCreateInfo * > ( self ) ;
Py_CLEAR ( py_info - > vertex_source ) ;
Py_CLEAR ( py_info - > fragment_source ) ;
2023-11-23 14:23:26 +01:00
Py_CLEAR ( py_info - > compute_source ) ;
2022-04-12 18:28:27 -03:00
Py_CLEAR ( py_info - > references ) ;
return 0 ;
}
# endif
static void pygpu_shader_info__tp_dealloc ( PyObject * self )
{
BPyGPUShaderCreateInfo * py_info = reinterpret_cast < BPyGPUShaderCreateInfo * > ( self ) ;
ShaderCreateInfo * info = reinterpret_cast < ShaderCreateInfo * > ( py_info - > info ) ;
delete info ;
# ifdef USE_GPU_PY_REFERENCES
PyObject_GC_UnTrack ( self ) ;
if ( py_info - > references | | py_info - > vertex_source | | py_info - > fragment_source ) {
pygpu_shader_info__tp_clear ( self ) ;
Py_XDECREF ( py_info - > vertex_source ) ;
Py_XDECREF ( py_info - > fragment_source ) ;
2023-11-23 14:23:26 +01:00
Py_XDECREF ( py_info - > compute_source ) ;
2022-04-12 18:28:27 -03:00
Py_XDECREF ( py_info - > references ) ;
}
2023-11-23 14:23:26 +01:00
2022-04-12 18:28:27 -03:00
# endif
2025-01-26 20:08:04 +01:00
Py_TYPE ( self ) - > tp_free ( self ) ;
2022-04-12 18:28:27 -03:00
}
2024-01-25 10:22:16 +11:00
PyDoc_STRVAR (
/* Wrap. */
pygpu_shader_info__tp_doc ,
" .. class:: GPUShaderCreateInfo() \n "
" \n "
" Stores and describes types and variables that are used in shader sources. \n " ) ;
2023-07-16 17:43:31 +10:00
PyTypeObject BPyGPUShaderCreateInfo_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT ( nullptr , 0 )
/*tp_name*/ " GPUShaderCreateInfo " ,
/*tp_basicsize*/ sizeof ( BPyGPUShaderCreateInfo ) ,
/*tp_itemsize*/ 0 ,
/*tp_dealloc*/ pygpu_shader_info__tp_dealloc ,
/*tp_vectorcall_offset*/ 0 ,
/*tp_getattr*/ nullptr ,
/*tp_setattr*/ nullptr ,
/*tp_compare*/ nullptr ,
/*tp_repr*/ nullptr ,
/*tp_as_number*/ nullptr ,
/*tp_as_sequence*/ nullptr ,
/*tp_as_mapping*/ nullptr ,
/*tp_hash*/ nullptr ,
/*tp_call*/ nullptr ,
/*tp_str*/ nullptr ,
/*tp_getattro*/ nullptr ,
/*tp_setattro*/ nullptr ,
/*tp_as_buffer*/ nullptr ,
2022-04-12 18:28:27 -03:00
# ifdef USE_GPU_PY_REFERENCES
2023-07-16 17:43:31 +10:00
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,
2022-04-12 18:28:27 -03:00
# else
2023-07-16 17:43:31 +10:00
/*tp_flags*/ Py_TPFLAGS_DEFAULT ,
2022-04-12 18:28:27 -03:00
# endif
2023-07-16 17:43:31 +10:00
/*tp_doc*/ pygpu_shader_info__tp_doc ,
# ifdef USE_GPU_PY_REFERENCES
/*tp_traverse*/ pygpu_shader_info__tp_traverse ,
# else
/*tp_traverse*/ nullptr ,
# endif
# ifdef USE_GPU_PY_REFERENCES
/*tp_clear*/ pygpu_shader_info__tp_clear ,
# else
/*tp_clear*/ nullptr ,
# endif
/*tp_richcompare*/ nullptr ,
/*tp_weaklistoffset*/ 0 ,
/*tp_iter*/ nullptr ,
/*tp_iternext*/ nullptr ,
/*tp_methods*/ pygpu_shader_info__tp_methods ,
/*tp_members*/ nullptr ,
/*tp_getset*/ nullptr ,
/*tp_base*/ nullptr ,
/*tp_dict*/ nullptr ,
/*tp_descr_get*/ nullptr ,
/*tp_descr_set*/ nullptr ,
/*tp_dictoffset*/ 0 ,
/*tp_init*/ nullptr ,
/*tp_alloc*/ nullptr ,
/*tp_new*/ pygpu_shader_info__tp_new ,
/*tp_free*/ nullptr ,
/*tp_is_gc*/ nullptr ,
/*tp_bases*/ nullptr ,
/*tp_mro*/ nullptr ,
/*tp_cache*/ nullptr ,
/*tp_subclasses*/ nullptr ,
/*tp_weaklist*/ nullptr ,
/*tp_del*/ nullptr ,
/*tp_version_tag*/ 0 ,
/*tp_finalize*/ nullptr ,
/*tp_vectorcall*/ nullptr ,
} ;
2022-04-12 18:28:27 -03:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public API
* \ { */
PyObject * BPyGPUStageInterfaceInfo_CreatePyObject ( GPUStageInterfaceInfo * interface )
{
BPyGPUStageInterfaceInfo * self ;
# ifdef USE_GPU_PY_REFERENCES
self = ( BPyGPUStageInterfaceInfo * ) _PyObject_GC_New ( & BPyGPUStageInterfaceInfo_Type ) ;
self - > references = PyList_New ( 0 ) ;
# else
self = PyObject_New ( BPyGPUStageInterfaceInfo , & BPyGPUStageInterfaceInfo_Type ) ;
# endif
self - > interface = interface ;
return ( PyObject * ) self ;
}
PyObject * BPyGPUShaderCreateInfo_CreatePyObject ( GPUShaderCreateInfo * info )
{
BPyGPUShaderCreateInfo * self ;
# ifdef USE_GPU_PY_REFERENCES
self = ( BPyGPUShaderCreateInfo * ) _PyObject_GC_New ( & BPyGPUShaderCreateInfo_Type ) ;
self - > vertex_source = nullptr ;
self - > fragment_source = nullptr ;
2023-11-23 14:23:26 +01:00
self - > compute_source = nullptr ;
2022-04-12 18:28:27 -03:00
self - > typedef_source = nullptr ;
self - > references = PyList_New ( 0 ) ;
# else
self = PyObject_New ( BPyGPUShaderCreateInfo , & BPyGPUShaderCreateInfo_Type ) ;
# endif
self - > info = info ;
self - > constants_total_size = 0 ;
return ( PyObject * ) self ;
}
/** \} */