@@ -359,6 +359,7 @@ def view_draw(self, context, depsgraph):
359359 if region .type == 'UI' :
360360 region .tag_redraw ()
361361
362+ global DISPLAY_DRAW
362363 if self .render_backend == 'OPENGL' :
363364 fbo = GL .gl_buffer (GL .GL_INT , 1 )
364365 GL .glGetIntegerv (GL .GL_FRAMEBUFFER_BINDING , fbo )
@@ -382,24 +383,33 @@ def view_draw(self, context, depsgraph):
382383 render_texture = Texture (resolution , GL .GL_RGBA8 , GL .GL_UNSIGNED_BYTE , pixels .buffer (),
383384 mag_filter = mag_filter )
384385
385- global DISPLAY_DRAW
386386 if DISPLAY_DRAW is None :
387- DISPLAY_DRAW = DisplayDraw ()
387+ DISPLAY_DRAW = DisplayDrawGL ()
388388 DISPLAY_DRAW .draw (fbo , render_texture )
389389 else :
390390 import gpu
391- from gpu_extras .presets import draw_texture_2d
392- data_format = 'FLOAT' # GPUTexture only supports 'FLOAT' buffer types
391+ data_size = len (pixels )
392+ w ,h = resolution
393+ if self .bridge .viewport_bit_depth == 8 :
394+ data_size = data_size // 4
395+ h = h // 4
396+ elif self .bridge .viewport_bit_depth == 16 :
397+ data_size = data_size // 2
398+ h = h // 2
399+ data_format = 'FLOAT' #Pretend we are uploading float data, since it's the only supported format.
393400 texture_format = 'RGBA32F'
394- #TODO do we need the sRGBConversion shader?
395- buffer = gpu .types .Buffer (data_format , len (pixels ), pixels .buffer ())
396- render_texture = gpu .types .GPUTexture (viewport_resolution , format = texture_format , data = buffer )
397- draw_texture_2d (render_texture , (0 , 0 ), render_texture .width , render_texture .height )
401+ data_as_float = (ctypes .c_float * data_size ).from_address (pixels ._buffer .data )
402+ buffer = gpu .types .Buffer (data_format , data_size , data_as_float )
403+ render_texture = gpu .types .GPUTexture ((w , h ), format = texture_format , data = buffer )
404+
405+ if DISPLAY_DRAW is None :
406+ DISPLAY_DRAW = DisplayDrawGPU ()
407+ DISPLAY_DRAW .draw (self .bridge .viewport_bit_depth , resolution , render_texture )
398408
399409
400410DISPLAY_DRAW = None
401411
402- class DisplayDraw ():
412+ class DisplayDrawGL ():
403413 def __init__ (self ):
404414 positions = [
405415 1.0 , 1.0 , 1.0 ,
@@ -425,6 +435,108 @@ def draw(self, fbo, texture):
425435 self .shader .bind ()
426436 self .quad .draw ()
427437
438+ class DisplayDrawGPU ():
439+ def __init__ (self ):
440+ import gpu
441+ from gpu_extras .batch import batch_for_shader
442+
443+ vertex_src = """
444+ void main()
445+ {
446+ IO_POSITION = IN_POSITION * vec3(1000, 1000, 0.5);
447+ gl_Position = vec4(IO_POSITION, 1);
448+ }
449+ """
450+
451+ pixel_src = """
452+ vec3 srgb_to_linear(vec3 srgb)
453+ {
454+ vec3 low = srgb / 12.92;
455+ vec3 high = pow((srgb + 0.055)/1.055, vec3(2.4));
456+ return mix(low, high, greaterThan(srgb, vec3(0.04045)));
457+ }
458+
459+ void main()
460+ {
461+ vec2 uv = IO_POSITION.xy * 0.5 + 0.5;
462+
463+ int divisor = 32 / bit_depth;
464+
465+ ivec2 output_texel = ivec2(vec2(output_res) * uv);
466+ int output_texel_linear = output_texel.y * output_res.x + output_texel.x;
467+
468+ int texel_linear_read = output_texel_linear / divisor;
469+ ivec2 texel_read = ivec2(texel_linear_read % output_res.x, texel_linear_read / output_res.x);
470+ int sub_texel_index = output_texel_linear % divisor;
471+
472+ vec4 texel_value = texelFetch(input_texture, texel_read, 0);
473+
474+ if(bit_depth == 32)
475+ {
476+ OUT_COLOR = texel_value;
477+ }
478+ else if(bit_depth == 16)
479+ {
480+ vec2 sub_texel_value = sub_texel_index == 0 ? texel_value.xy : texel_value.zw;
481+
482+ uint packed_xy = floatBitsToUint(sub_texel_value.x);
483+ uint packed_yz = floatBitsToUint(sub_texel_value.y);
484+
485+ OUT_COLOR.rg = unpackHalf2x16(packed_xy);
486+ OUT_COLOR.ba = unpackHalf2x16(packed_yz);
487+ }
488+ else if(bit_depth == 8)
489+ {
490+ float sub_texel_value = texel_value[sub_texel_index];
491+ uint packed_value = floatBitsToUint(sub_texel_value);
492+ OUT_COLOR = unpackUnorm4x8(packed_value);
493+ OUT_COLOR.rgb = srgb_to_linear(OUT_COLOR.rgb);
494+ }
495+ else{
496+ OUT_COLOR = vec4(1,1,0,1);
497+ }
498+ }
499+ """
500+
501+ self .iface = gpu .types .GPUStageInterfaceInfo ("IFace" )
502+ self .iface .smooth ('VEC3' , "IO_POSITION" )
503+
504+ self .sh_info = gpu .types .GPUShaderCreateInfo ()
505+ self .sh_info .push_constant ('INT' , "bit_depth" )
506+ self .sh_info .push_constant ('IVEC2' , "output_res" )
507+ self .sh_info .sampler (0 , 'FLOAT_2D' , "input_texture" )
508+ self .sh_info .vertex_source (vertex_src )
509+ self .sh_info .vertex_in (0 , 'VEC3' , "IN_POSITION" )
510+ self .sh_info .vertex_out (self .iface )
511+ self .sh_info .fragment_source (pixel_src )
512+ self .sh_info .fragment_out (0 , 'VEC4' , "OUT_COLOR" )
513+
514+ self .shader = gpu .shader .create_from_info (self .sh_info )
515+
516+ positions = [
517+ ( 1.0 , 1.0 , 1.0 ),
518+ ( 1.0 , - 1.0 , 1.0 ),
519+ (- 1.0 , - 1.0 , 1.0 ),
520+ (- 1.0 , 1.0 , 1.0 ),
521+ ]
522+ indices = [
523+ (0 , 1 , 3 ),
524+ (1 , 2 , 3 ),
525+ ]
526+
527+ self .quad = batch_for_shader (
528+ self .shader , 'TRIS' ,
529+ {"IN_POSITION" : positions },
530+ indices = indices
531+ )
532+
533+ def draw (self , bit_depth , resolution , texture ):
534+ self .shader .bind ()
535+ self .shader .uniform_int ("bit_depth" , bit_depth )
536+ self .shader .uniform_int ("output_res" , resolution )
537+ self .shader .uniform_sampler ("input_texture" , texture )
538+ self .quad .draw (self .shader )
539+
428540
429541class OT_MaltRenderDocCapture (bpy .types .Operator ):
430542 bl_idname = "wm.malt_renderdoc_capture"
0 commit comments