The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates.

godotengine.org | Twitter

+1 vote

So I've managed to get a compute pipeline working, but now I'm trying to render a triangle using a render pipeline. I've wrote the following code by referencing the source code and as far as I can see it should work. I very limited experience with GPU related things so I might very well be missing something completely.

extends Node3D
@onready var rd := RenderingServer.get_rendering_device()

func _ready():
    var shader_file: RDShaderFile = load("res://RenderTest.glsl")
    var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
    var shader := rd.shader_create_from_spirv(shader_spirv)

    # Create format
    var vertex_attrs = [RDVertexAttribute.new()]
    vertex_attrs[0].format = RenderingDevice.DATA_FORMAT_R8G8B8_SNORM
    vertex_attrs[0].location = 0
    var vertex_format = rd.vertex_format_create(vertex_attrs)


    # Create Vertex buffers
    var points := PackedFloat32Array([
        0, 0, 0,
        0, 1, 0,
        1, 1, 0,
    ])
    var points_bytes := points.to_byte_array()
    var vertex_buffers := [rd.vertex_buffer_create(points_bytes.size(), points_bytes)]
    # Create vertex array
    var vertex_array := rd.vertex_array_create(3, vertex_format, vertex_buffers)


    # Blend
    var blend = RDPipelineColorBlendState.new()
    blend.attachments.push_back(RDPipelineColorBlendStateAttachment.new())

    # Create empty framebuffer size of viewport
    var rect_size = get_viewport().get_visible_rect().size
    var screen_size = Vector2i(rect_size.x, rect_size.y)
    var framebuffer = rd.framebuffer_create_empty(screen_size)


    # Define pipe
    var pipeline := rd.render_pipeline_create(
        shader,
        rd.screen_get_framebuffer_format(),
        vertex_format,
        RenderingDevice.RENDER_PRIMITIVE_TRIANGLES,
        RDPipelineRasterizationState.new(),
        RDPipelineMultisampleState.new(),
        RDPipelineDepthStencilState.new(),
        blend,
        0
    )

    # Create render pipeline
    if rd.render_pipeline_is_valid(pipeline):
        var draw_list := rd.draw_list_begin(framebuffer, RenderingDevice.INITIAL_ACTION_DROP, RenderingDevice.FINAL_ACTION_DISCARD, RenderingDevice.INITIAL_ACTION_DROP, RenderingDevice.FINAL_ACTION_DISCARD)
        # Bind pipe
        rd.draw_list_bind_render_pipeline(draw_list, pipeline)
        # Bind vertex array
        rd.draw_list_bind_vertex_array(draw_list, vertex_array)
        # Render
        rd.draw_list_draw(draw_list, false, 1)
        rd.draw_list_end()
    else:
        print("Invalid pipe")

And this is the shader file, I have limitex experience with shaders but as far as I understand this should be sufficient to render a mesh. Everything executes without errors, but no triangle is displayed...

#[vertex]
#version 450 core

layout(location = 0) in vec3 vertex_attrib;

void main()
{
    gl_Position = vec4(vertex_attrib, 1.0);
}


#[fragment]
#version 450 core

layout (location = 0) out vec4 frag_color;

void main()
{
    //Default color
    frag_color = vec4(1,1,1,1);
}

Note that the function "vertexarraycreate" is not currently (commit cf194847) bound, as pre this gitHub issue, so I added the following line of code to rendering_device.cpp, thus making it accessible, and recompiled. As far as I can see this works fine.

ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "buffers"), &RenderingDevice::_vertex_array_create)
Godot version 4.0
in Engine by (20 points)
retagged by

Note that the function "vertexarraycreate" is not currently (commit cf194847) bound, as pre this gitHub issue, so I added the following line of code to rendering_device.cpp, thus making it accessible, and recompiled. As far as I can see this works fine.

The method is bound as of 4.0.stable: https://github.com/godotengine/godot/blob/92b7a9603aa2395be6bf361067096538ba393c45/servers/rendering/rendering_device.cpp#L729

1 Answer

0 votes

In case anyone wants this to work, there's a few fiddly bugs in the code above.

Firstly, the vertex data format should be RenderingDevice.DATA_FORMAT_R32G32B32_SFLOAT

Secondly, it needs a stride in there (which is 3 * 32 bit floats = 4*3 = 12)
vertex_attrs[0].stride=4*3

My (working) code looks like the below (possibly give or take some class variables which aren't defined in the code below)

```

rd= RenderingServer.create_local_rendering_device()
var tex_format:=RDTextureFormat.new()
var tex_view:=RDTextureView.new()
tex_format.texture_type=RenderingDevice.TEXTURE_TYPE_2D
tex_format.height=1024
tex_format.width=1024
tex_format.format=RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT
tex_format.usage_bits=(RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT) 
framebuf_texture=rd.texture_create(tex_format,tex_view)

var shader_file = load("res://ripple_calc_float.glsl")
var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
var shader := rd.shader_create_from_spirv(shader_spirv,"RenderTestJoe")
print(shader.is_valid())
var points := PackedFloat32Array([
    0.0, 0.0, 0.0,
    0.0, 1.0 ,0.0,
    1.0,1.0,0.0,
    1.0,0.0,0.0
])
var points_bytes := points.to_byte_array()

var indices:= PackedByteArray()
indices.resize(12)
var pos:=0
for x in [0,2,1,0,2,3]:
    indices.encode_u16(pos,x)
    pos+=2
var index_buffer=rd.index_buffer_create(6,RenderingDevice.INDEX_BUFFER_FORMAT_UINT16,indices)
index_array=rd.index_array_create(index_buffer,0,6)

var vertex_buffers := [
    rd.vertex_buffer_create(points_bytes.size(), points_bytes),
]

var vertex_attrs = [ RDVertexAttribute.new()]
vertex_attrs[0].format = RenderingDevice.DATA_FORMAT_R32G32B32_SFLOAT
vertex_attrs[0].location = 0
vertex_attrs[0].stride=4*3
var vertex_format = rd.vertex_format_create(vertex_attrs)
vertex_array = rd.vertex_array_create(4, vertex_format, vertex_buffers)

var blend = RDPipelineColorBlendState.new()
var blend_attachment =RDPipelineColorBlendStateAttachment.new()
blend_attachment.write_r=true
blend_attachment.write_g=true
blend_attachment.write_b=true
blend_attachment.enable_blend=false
blend.attachments.push_back(blend_attachment)   

var attachments=[]
var af:=RDAttachmentFormat.new()
af.set_format(tex_format.format)
af.set_samples(RenderingDevice.TEXTURE_SAMPLES_1)
af.usage_flags = RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT
attachments.push_back(af)   
var framebuf_format=rd.framebuffer_format_create(attachments)

# second param means to check that this framebuffer has correct format
framebuffer = rd.framebuffer_create([framebuf_texture],framebuf_format)
print(rd.framebuffer_is_valid(framebuffer))
pipeline = rd.render_pipeline_create(
    shader,
    framebuf_format,
    vertex_format,
    RenderingDevice.RENDER_PRIMITIVE_TRIANGLES,
    RDPipelineRasterizationState.new(),
    RDPipelineMultisampleState.new(),
    RDPipelineDepthStencilState.new(),
    blend
)

print(rd.render_pipeline_is_valid(pipeline))
clear_color_values= PackedColorArray([Color(1,1,1,1)])

var draw_list := rd.draw_list_begin(framebuffer, RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ, RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ,clear_color_values)
rd.draw_list_bind_render_pipeline(draw_list, pipeline)
rd.draw_list_bind_vertex_array(draw_list, vertex_array)
rd.draw_list_bind_index_array(draw_list,index_array)
rd.draw_list_draw(draw_list, true, 2)
rd.draw_list_end()
var td=rd.texture_get_data(framebuf_texture,0)

```

by (14 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.