Merge branch 'main' into f/framegraph-v2
This commit is contained in:
		
						commit
						df50759303
					
				@ -14,6 +14,25 @@ struct VSOutput
 | 
			
		||||
    float4 Pos : SV_POSITION;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) {
 | 
			
		||||
    VSOutput output = (VSOutput)0;
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
            END
 | 
			
		||||
            
 | 
			
		||||
            
 | 
			
		||||
            dx11 BEGIN
 | 
			
		||||
#include "common.hlsl"
 | 
			
		||||
 | 
			
		||||
struct VSInput
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VSOutput
 | 
			
		||||
{
 | 
			
		||||
    float4 Pos : SV_POSITION;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) {
 | 
			
		||||
    VSOutput output = (VSOutput)0;
 | 
			
		||||
    return output;
 | 
			
		||||
@ -27,6 +46,21 @@ struct PSOutput {
 | 
			
		||||
float4 Color : SV_TARGET0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PSOutput PsMain(void) {
 | 
			
		||||
    PSOutput output = (PSOutput)0;
 | 
			
		||||
    output.Color[0] = 0;
 | 
			
		||||
    output.Color[1] = 0;
 | 
			
		||||
    output.Color[2] = 0;
 | 
			
		||||
    output.Color[3] = 0;
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
            END
 | 
			
		||||
            
 | 
			
		||||
            dx11 BEGIN
 | 
			
		||||
struct PSOutput {
 | 
			
		||||
float4 Color : SV_TARGET0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PSOutput PsMain(void) {
 | 
			
		||||
    PSOutput output = (PSOutput)0;
 | 
			
		||||
    output.Color[0] = 0;
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ project('rtengine', ['c', 'cpp'],
 | 
			
		||||
  default_options: ['buildtype=debug', 
 | 
			
		||||
    'b_sanitize=address', 
 | 
			
		||||
    'c_std=c17', 
 | 
			
		||||
    'cpp_std=c++14',
 | 
			
		||||
    'cpp_std=c++20',
 | 
			
		||||
    'warning_level=3',
 | 
			
		||||
    'werror=true',
 | 
			
		||||
    'b_vscrt=static_from_buildtype',
 | 
			
		||||
@ -85,6 +85,8 @@ if get_option('default_library') == 'static'
 | 
			
		||||
    engine_link_libs = [runtime_lib, gfx_lib, app_lib, vk_renderer_lib]
 | 
			
		||||
  elif get_option('static_renderer') == 'null'
 | 
			
		||||
    engine_link_libs = [runtime_lib, gfx_lib, app_lib, null_renderer_lib]
 | 
			
		||||
  elif get_option('static_renderer') == 'dx11'
 | 
			
		||||
    engine_link_libs = [runtime_lib, gfx_lib, app_lib, dx11_renderer_lib]
 | 
			
		||||
  else
 | 
			
		||||
    error('Invalid static_renderer option ', get_option('static_renderer'))
 | 
			
		||||
  endif
 | 
			
		||||
 | 
			
		||||
@ -2,5 +2,6 @@ option('static_renderer', type : 'string', value : 'vk', description : 'Name of
 | 
			
		||||
option('use_xlib', type : 'boolean', value : false, description : 'Use Xlib for window creation under linux')
 | 
			
		||||
option('error_report_debugbreak', type : 'boolean', value : true, description : 'Debugbreak in ReportError')
 | 
			
		||||
option('enable_dxc_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dxc-based shader compiler.')
 | 
			
		||||
option('enable_dx11_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dx11-bases shader compiler.')
 | 
			
		||||
option('game_as_subdir', type : 'boolean', value : false, description : 'If true, adds the directory "src/game" to the build.')
 | 
			
		||||
 | 
			
		||||
option('build_dx11', type : 'boolean', value : true, description : 'Enables/disables the build of the dx11 renderer.')
 | 
			
		||||
							
								
								
									
										89
									
								
								src/asset_compiler/dx11_shader_compiler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/asset_compiler/dx11_shader_compiler.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
#include <d3dcompiler.h>
 | 
			
		||||
 | 
			
		||||
#include "shader_compiler.h"
 | 
			
		||||
 | 
			
		||||
extern "C" rt_shader_bytecode CompileDX11Shader(rt_shader_stage stage,
 | 
			
		||||
                                                rt_shader_optimization_level optimization,
 | 
			
		||||
                                                rt_text_span code,
 | 
			
		||||
                                                const char *file_path,
 | 
			
		||||
                                                rt_arena *arena) {
 | 
			
		||||
    rt_shader_bytecode bytecode = {};
 | 
			
		||||
 | 
			
		||||
    D3D_SHADER_MACRO defines[] = {
 | 
			
		||||
        {"RT_DX11",  "1"},
 | 
			
		||||
        {     NULL, NULL},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    LPCSTR target = NULL;
 | 
			
		||||
    LPCSTR entrypoint = NULL;
 | 
			
		||||
    switch (stage) {
 | 
			
		||||
    case RT_SHADER_STAGE_VERTEX:
 | 
			
		||||
        target = "vs_5_0";
 | 
			
		||||
        entrypoint = "VsMain";
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_SHADER_STAGE_FRAGMENT:
 | 
			
		||||
        target = "ps_5_0";
 | 
			
		||||
        entrypoint = "PsMain";
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_SHADER_STAGE_COMPUTE:
 | 
			
		||||
        target = "cs_5_0";
 | 
			
		||||
        entrypoint = "CsMain";
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        rtLog("AC", "Tried to compile an invalid shader stage %u for %s", stage, file_path);
 | 
			
		||||
        return bytecode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UINT flags = D3DCOMPILE_PARTIAL_PRECISION | D3DCOMPILE_WARNINGS_ARE_ERRORS;
 | 
			
		||||
    switch (optimization) {
 | 
			
		||||
    case RT_SHADER_OPTIMIZATION_NONE:
 | 
			
		||||
        flags |= D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_OPTIMIZATION_LEVEL0;
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_SHADER_OPTIMIZATION_SIZE:
 | 
			
		||||
        flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2;
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_SHADER_OPTIMIZATION_SPEED:
 | 
			
		||||
        flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
    flags |= D3DCOMPILE_DEBUG;
 | 
			
		||||
#endif
 | 
			
		||||
    ID3DBlob *bytes = nullptr, *error = nullptr;
 | 
			
		||||
    if (FAILED(D3DCompile2(code.start,
 | 
			
		||||
                           code.length,
 | 
			
		||||
                           file_path,
 | 
			
		||||
                           defines,
 | 
			
		||||
                           D3D_COMPILE_STANDARD_FILE_INCLUDE,
 | 
			
		||||
                           entrypoint,
 | 
			
		||||
                           target,
 | 
			
		||||
                           flags,
 | 
			
		||||
                           0,
 | 
			
		||||
                           0,
 | 
			
		||||
                           nullptr,
 | 
			
		||||
                           0,
 | 
			
		||||
                           &bytes,
 | 
			
		||||
                           &error))) {
 | 
			
		||||
        if (error) {
 | 
			
		||||
            rtLog("AC",
 | 
			
		||||
                  "Shader compilation failed (%s): %s",file_path,
 | 
			
		||||
                  (const char *)error->GetBufferPointer());
 | 
			
		||||
            error->Release();
 | 
			
		||||
            return bytecode;
 | 
			
		||||
        } else {
 | 
			
		||||
            rtLog("AC", "Shader compilation failed (%s): NO ERROR INFORMATION", file_path);
 | 
			
		||||
            return bytecode;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bytecode.bytes = rtArenaPush(arena, bytes->GetBufferSize());
 | 
			
		||||
    if (bytecode.bytes) {
 | 
			
		||||
        bytecode.len = bytes->GetBufferSize();
 | 
			
		||||
        memcpy(bytecode.bytes, bytes->GetBufferPointer(), bytecode.len);
 | 
			
		||||
    } else {
 | 
			
		||||
        rtLog("AC", "Out of memory while compiling %s", file_path);
 | 
			
		||||
    }
 | 
			
		||||
    bytes->Release();
 | 
			
		||||
 | 
			
		||||
    return bytecode;
 | 
			
		||||
}
 | 
			
		||||
@ -62,6 +62,9 @@ static char *GenerateShaderName(rt_shader_type type,
 | 
			
		||||
    case RT_SHADER_TYPE_VULKAN:
 | 
			
		||||
        type_str = ":vk";
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_SHADER_TYPE_DX11:
 | 
			
		||||
        type_str = ":dx11";
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@ -135,6 +138,8 @@ static rt_result ParseShader(rt_parse_state *state,
 | 
			
		||||
            rt_shader_type in_file_type = RT_SHADER_TYPE_INVALID;
 | 
			
		||||
            if (rtCompareSpanToString(shader->attribute, "vk") == 0) {
 | 
			
		||||
                in_file_type = RT_SHADER_TYPE_VULKAN;
 | 
			
		||||
            } else if (rtCompareSpanToString(shader->attribute, "dx11") == 0) {
 | 
			
		||||
                in_file_type = RT_SHADER_TYPE_DX11;
 | 
			
		||||
            } else {
 | 
			
		||||
                rtReportError("GFX",
 | 
			
		||||
                              "Invalid renderer backend"
 | 
			
		||||
@ -230,6 +235,8 @@ static rt_result ParsePipeline(rt_parse_state *state,
 | 
			
		||||
    rt_shader_type type = RT_SHADER_TYPE_INVALID;
 | 
			
		||||
    if (strcmp(rt_Renderer.s, "vk") == 0)
 | 
			
		||||
        type = RT_SHADER_TYPE_VULKAN;
 | 
			
		||||
    else if (strcmp(rt_Renderer.s, "dx11") == 0)
 | 
			
		||||
        type = RT_SHADER_TYPE_DX11;
 | 
			
		||||
 | 
			
		||||
    if (type == RT_SHADER_TYPE_INVALID) {
 | 
			
		||||
        result = RT_ASSET_PROCESSING_FAILED;
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,13 @@ if get_option('enable_dxc_shader_compiler')
 | 
			
		||||
  ac_cargs += '-DRT_BUILD_DXC_SHADER_COMPILER'
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if get_option('enable_dx11_shader_compiler')
 | 
			
		||||
  ac_cargs += '-DRT_BUILD_DX11_SHADER_COMPILER'
 | 
			
		||||
  ac_sources += ['dx11_shader_compiler.cpp']
 | 
			
		||||
  d3dcompiler_dep = declare_dependency(link_args : ['-lD3DCompiler'])
 | 
			
		||||
  ac_deps += d3dcompiler_dep
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
asset_compiler = static_library('asset_compiler',
 | 
			
		||||
  'asset_compiler.h',
 | 
			
		||||
  'description_parser.h',
 | 
			
		||||
 | 
			
		||||
@ -8,10 +8,18 @@ extern rt_shader_bytecode CompileVulkanShader(rt_shader_stage stage,
 | 
			
		||||
                                              rt_arena *arena);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RT_BUILD_DX11_SHADER_COMPILER
 | 
			
		||||
extern rt_shader_bytecode CompileDX11Shader(rt_shader_stage stage,
 | 
			
		||||
                                            rt_shader_optimization_level optimization,
 | 
			
		||||
                                            rt_text_span code,
 | 
			
		||||
                                            const char *file_path,
 | 
			
		||||
                                            rt_arena *arena);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static rt_shader_bytecode CompileNullShader(rt_shader_stage stage,
 | 
			
		||||
                                            rt_shader_optimization_level optimization,
 | 
			
		||||
                                            rt_text_span code,
 | 
			
		||||
    const char *file_path,
 | 
			
		||||
                                            const char *file_path,
 | 
			
		||||
                                            rt_arena *arena) {
 | 
			
		||||
    RT_UNUSED(stage);
 | 
			
		||||
    RT_UNUSED(optimization);
 | 
			
		||||
@ -24,8 +32,11 @@ static rt_shader_bytecode CompileNullShader(rt_shader_stage stage,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef rt_shader_bytecode
 | 
			
		||||
shader_compiler_fn(rt_shader_stage, rt_shader_optimization_level, rt_text_span, const char *, rt_arena *);
 | 
			
		||||
typedef rt_shader_bytecode shader_compiler_fn(rt_shader_stage,
 | 
			
		||||
                                              rt_shader_optimization_level,
 | 
			
		||||
                                              rt_text_span,
 | 
			
		||||
                                              const char *,
 | 
			
		||||
                                              rt_arena *);
 | 
			
		||||
 | 
			
		||||
static shader_compiler_fn *_compiler_funcs[RT_SHADER_TYPE_count] = {
 | 
			
		||||
    CompileNullShader,
 | 
			
		||||
@ -36,6 +47,11 @@ static shader_compiler_fn *_compiler_funcs[RT_SHADER_TYPE_count] = {
 | 
			
		||||
    CompileNullShader,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RT_BUILD_DX11_SHADER_COMPILER
 | 
			
		||||
    CompileDX11Shader,
 | 
			
		||||
#else
 | 
			
		||||
    CompileNullShader,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
rt_shader_bytecode CompileShader(rt_shader_type type,
 | 
			
		||||
 | 
			
		||||
@ -13,29 +13,7 @@ void RegisterCVars(void) {
 | 
			
		||||
 | 
			
		||||
static rt_framegraph *_framegraph;
 | 
			
		||||
 | 
			
		||||
static void PassPrepare(rt_render_pass_id pass,
 | 
			
		||||
                        const rt_render_target_write *writes,
 | 
			
		||||
                        uint32_t write_count,
 | 
			
		||||
                        const rt_render_target_read *reads,
 | 
			
		||||
                        uint32_t read_count) {
 | 
			
		||||
    // rtLog("GAME", "Prepare pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PassExecute(rt_render_pass_id pass,
 | 
			
		||||
                        const rt_render_target_write *writes,
 | 
			
		||||
                        uint32_t write_count,
 | 
			
		||||
                        const rt_render_target_read *reads,
 | 
			
		||||
                        uint32_t read_count) {
 | 
			
		||||
    // rtLog("GAME", "Execute pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PassFinalize(rt_render_pass_id pass,
 | 
			
		||||
                         const rt_render_target_write *writes,
 | 
			
		||||
                         uint32_t write_count,
 | 
			
		||||
                         const rt_render_target_read *reads,
 | 
			
		||||
                         uint32_t read_count) {
 | 
			
		||||
    // rtLog("GAME", "Finalize pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
static rt_render_target_handle _rt;
 | 
			
		||||
 | 
			
		||||
/* Called after the runtime has finished its initialization and before entering the main-loop*/
 | 
			
		||||
void Init(void) {
 | 
			
		||||
@ -44,56 +22,13 @@ void Init(void) {
 | 
			
		||||
 | 
			
		||||
    rtWaitForAssetProcessing();
 | 
			
		||||
 | 
			
		||||
    rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    rt_resource_id resid = rtGetResourceID("assets/forward.framegraph");
 | 
			
		||||
    size_t size          = rtGetResourceSize(resid);
 | 
			
		||||
    rt_resource *res     = rtArenaPush(temp.arena, size);
 | 
			
		||||
    rtGetResource(resid, res);
 | 
			
		||||
 | 
			
		||||
    _framegraph = rtCreateFramegraph(res->data);
 | 
			
		||||
 | 
			
		||||
    rt_render_pass_bind_fns bind = {.Execute  = PassExecute,
 | 
			
		||||
                                    .Prepare  = PassPrepare,
 | 
			
		||||
                                    .Finalize = PassFinalize};
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("forward", sizeof("forward") - 1), &bind);
 | 
			
		||||
#else
 | 
			
		||||
    rt_resource_id resid = rtGetResourceID("assets/test.framegraph");
 | 
			
		||||
    size_t size          = rtGetResourceSize(resid);
 | 
			
		||||
    rt_resource *res     = rtArenaPush(temp.arena, size);
 | 
			
		||||
    rtGetResource(resid, res);
 | 
			
		||||
 | 
			
		||||
    _framegraph = rtCreateFramegraph(res->data);
 | 
			
		||||
 | 
			
		||||
    rt_render_pass_bind_fns bind = {.Execute  = PassExecute,
 | 
			
		||||
                                    .Prepare  = PassPrepare,
 | 
			
		||||
                                    .Finalize = PassFinalize};
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass0", sizeof("pass0") - 1), &bind);
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass1", sizeof("pass1") - 1), &bind);
 | 
			
		||||
 | 
			
		||||
    rt_v2 vertices[] = {
 | 
			
		||||
        {   0,  0.5},
 | 
			
		||||
        { 0.5, -0.5},
 | 
			
		||||
        {-0.5, -0.5}
 | 
			
		||||
    };
 | 
			
		||||
    rt_buffer_info info = {
 | 
			
		||||
        .type  = RT_BUFFER_TYPE_VERTEX,
 | 
			
		||||
        .usage = RT_BUFFER_USAGE_STATIC,
 | 
			
		||||
        .size  = sizeof(vertices),
 | 
			
		||||
        .data  = vertices,
 | 
			
		||||
    };
 | 
			
		||||
    rt_buffer_handle buf;
 | 
			
		||||
    g_renderer.CreateBuffers(1, &info, &buf);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
    _rt = g_renderer.GetSwapchainRenderTarget();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called after exiting the main-loop and before the runtime starts its shutdown */
 | 
			
		||||
void Shutdown(void) {
 | 
			
		||||
    rtLog("GAME", "Shutdown");
 | 
			
		||||
    rtShutdownAssetCompiler();
 | 
			
		||||
    rtDestroyFramegraph(_framegraph);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update(unsigned int frame_id) {
 | 
			
		||||
@ -101,5 +36,20 @@ void Update(unsigned int frame_id) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Render(unsigned int frame_id) {
 | 
			
		||||
    rtExecuteFramegraph(_framegraph, frame_id);
 | 
			
		||||
    rt_alloc_command_buffer_info info = {RT_GRAPHICS_QUEUE};
 | 
			
		||||
    rt_command_buffer_handle cmd;
 | 
			
		||||
    g_renderer.AllocCommandBuffers(1, &info, &cmd);
 | 
			
		||||
    
 | 
			
		||||
    rt_cmd_begin_pass_info pass_info = {
 | 
			
		||||
        .color_buffer_count = 1,
 | 
			
		||||
        .color_buffers = {_rt},
 | 
			
		||||
        .color_buffer_loads = {RT_PASS_LOAD_MODE_CLEAR},
 | 
			
		||||
        .color_buffer_clear_values = {{.color = {1.f, 0.f, 0.f, 1.f}}},
 | 
			
		||||
        .name               = "testme",
 | 
			
		||||
    };
 | 
			
		||||
    g_renderer.CmdBeginPass(cmd, &pass_info);
 | 
			
		||||
    g_renderer.CmdEndPass(cmd);
 | 
			
		||||
 | 
			
		||||
    rt_submit_command_buffers_info submit = {.command_buffer_count = 1, .command_buffers = &cmd};
 | 
			
		||||
    g_renderer.SubmitCommandBuffers(RT_GRAPHICS_QUEUE, &submit);
 | 
			
		||||
}
 | 
			
		||||
@ -20,6 +20,9 @@ extern "C" {
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wpedantic"
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#pragma warning(push)
 | 
			
		||||
#pragma warning(disable : 4201) /* anonymous struct */
 | 
			
		||||
#endif
 | 
			
		||||
typedef union {
 | 
			
		||||
    float v[4];
 | 
			
		||||
@ -32,6 +35,8 @@ typedef union {
 | 
			
		||||
} rt_color;
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* NOTE(kevin): When you add a value here, you need to handle them in
 | 
			
		||||
@ -59,6 +64,10 @@ typedef enum {
 | 
			
		||||
    RT_PIXEL_FORMAT_count,
 | 
			
		||||
} rt_pixel_format;
 | 
			
		||||
 | 
			
		||||
RT_INLINE int rtIsDepthFormat(rt_pixel_format format) {
 | 
			
		||||
    return format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8 || format == RT_PIXEL_FORMAT_DEPTH32;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* In renderer_api.h -> Not necessary for almost all gfx usage */
 | 
			
		||||
typedef struct rt_renderer_init_info_s rt_renderer_init_info;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ static bool _renderer_loaded = false;
 | 
			
		||||
RT_DLLEXPORT
 | 
			
		||||
RT_CVAR_S(rt_Renderer,
 | 
			
		||||
          "Select the render backend. Available options: [vk, null], Default: vk",
 | 
			
		||||
          "vk");
 | 
			
		||||
          "dx11");
 | 
			
		||||
 | 
			
		||||
#ifdef RT_STATIC_LIB
 | 
			
		||||
extern void RT_RENDERER_API_FN(RegisterCVars)(void);
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
/* Handles for backend objects */
 | 
			
		||||
 | 
			
		||||
#define RT_RENDERER_BACKEND_HANDLE_MAX_INDEX ((1u<<24)-1)
 | 
			
		||||
#define RT_RENDER_BACKEND_HANDLE_MAX_INDEX ((1u<<24)-1)
 | 
			
		||||
#define RT_RENDER_BACKEND_HANDLE_MAX_VERSION 255
 | 
			
		||||
 | 
			
		||||
#define RT_RENDER_BACKEND_HANDLE(name)                                                             \
 | 
			
		||||
@ -87,6 +87,7 @@ typedef struct {
 | 
			
		||||
typedef enum {
 | 
			
		||||
    RT_SHADER_TYPE_INVALID,
 | 
			
		||||
    RT_SHADER_TYPE_VULKAN,
 | 
			
		||||
    RT_SHADER_TYPE_DX11,
 | 
			
		||||
 | 
			
		||||
    RT_SHADER_TYPE_count,
 | 
			
		||||
} rt_shader_type;
 | 
			
		||||
 | 
			
		||||
@ -6,3 +6,4 @@ subdir('app_framework')
 | 
			
		||||
# Renderer libs
 | 
			
		||||
subdir('renderer/vk')
 | 
			
		||||
subdir('renderer/null')
 | 
			
		||||
subdir('renderer/dx11')
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										146
									
								
								src/renderer/dx11/buffers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/renderer/dx11/buffers.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
#include "runtime/threading_helpers.hpp"
 | 
			
		||||
 | 
			
		||||
#include "device_objects.hpp"
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_Dx11MaxBuffers,
 | 
			
		||||
          "Maximum number of simultaneously existing buffers. Default: 4096",
 | 
			
		||||
          4096);
 | 
			
		||||
 | 
			
		||||
static rt_buffer *_buffers;
 | 
			
		||||
static rt_buffer *_first_free;
 | 
			
		||||
static rt_mutex *_lock;
 | 
			
		||||
 | 
			
		||||
rt_result InitBufferManagement() {
 | 
			
		||||
    _buffers =
 | 
			
		||||
        reinterpret_cast<rt_buffer *>(calloc((size_t)rt_Dx11MaxBuffers.i, sizeof(rt_buffer)));
 | 
			
		||||
    if (!_buffers) {
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock = rtCreateMutex();
 | 
			
		||||
    if (!_lock) {
 | 
			
		||||
        free(_buffers);
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _first_free = _buffers + 2;
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxBuffers.i; ++i) {
 | 
			
		||||
        _buffers[i].next_free = &_buffers[i + 1];
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownBufferManagement() {
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxBuffers.i; ++i) {
 | 
			
		||||
        if (_buffers[i].buffer)
 | 
			
		||||
            _buffers[i].buffer->Release();
 | 
			
		||||
    }
 | 
			
		||||
    free(_buffers);
 | 
			
		||||
    rtDestroyMutex(_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_buffer *rtGetBuffer(rt_buffer_handle handle) {
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxBuffers.i)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    auto lg = rtAutoLock(_lock);
 | 
			
		||||
    if (handle.version != _buffers[handle.index].version)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    return &_buffers[handle.index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count,
 | 
			
		||||
                                                       const rt_buffer_info *info,
 | 
			
		||||
                                                       rt_buffer_handle *p_buffers) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        rtLockMutex(_lock);
 | 
			
		||||
        rt_buffer *slot = _first_free;
 | 
			
		||||
        if (slot)
 | 
			
		||||
            _first_free = slot->next_free;
 | 
			
		||||
        rtUnlockMutex(_lock);
 | 
			
		||||
 | 
			
		||||
        if (!slot) {
 | 
			
		||||
            rtLog("dx11", "Failed to allocate a command buffer slot.");
 | 
			
		||||
            rtLockMutex(_lock);
 | 
			
		||||
            for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                rt_buffer *s = &_buffers[p_buffers[j].index];
 | 
			
		||||
                s->next_free = _first_free;
 | 
			
		||||
                _first_free  = s;
 | 
			
		||||
                _first_free  = s;
 | 
			
		||||
            }
 | 
			
		||||
            rtUnlockMutex(_lock);
 | 
			
		||||
            return RT_OUT_OF_MEMORY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
 | 
			
		||||
        if (info[i].usage == RT_BUFFER_USAGE_STATIC) {
 | 
			
		||||
            usage = D3D11_USAGE_IMMUTABLE;
 | 
			
		||||
        } else if (info[i].usage == RT_BUFFER_USAGE_DYNAMIC) {
 | 
			
		||||
            usage = D3D11_USAGE_DEFAULT;
 | 
			
		||||
        } else if (info[i].usage == RT_BUFFER_USAGE_TRANSIENT) {
 | 
			
		||||
            usage = D3D11_USAGE_DYNAMIC;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        UINT bind_flags = D3D11_BIND_UNORDERED_ACCESS;
 | 
			
		||||
        if (info[i].type == RT_BUFFER_TYPE_VERTEX)
 | 
			
		||||
            bind_flags = D3D11_BIND_VERTEX_BUFFER;
 | 
			
		||||
        else if (info[i].type == RT_BUFFER_TYPE_INDEX)
 | 
			
		||||
            bind_flags = D3D11_BIND_INDEX_BUFFER;
 | 
			
		||||
        else if (info[i].type == RT_BUFFER_TYPE_UNIFORM)
 | 
			
		||||
            bind_flags = D3D11_BIND_CONSTANT_BUFFER;
 | 
			
		||||
        else if (info[i].type == RT_BUFFER_TYPE_STORAGE)
 | 
			
		||||
            bind_flags = D3D11_BIND_UNORDERED_ACCESS;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        D3D11_BUFFER_DESC desc   = {};
 | 
			
		||||
        desc.ByteWidth           = static_cast<UINT>(((info[i].size + 15) / 16) * 16);
 | 
			
		||||
        desc.Usage               = usage;
 | 
			
		||||
        desc.BindFlags           = bind_flags;
 | 
			
		||||
        desc.CPUAccessFlags      = 0;
 | 
			
		||||
        desc.MiscFlags           = 0;
 | 
			
		||||
        desc.StructureByteStride = 1;
 | 
			
		||||
 | 
			
		||||
        D3D11_SUBRESOURCE_DATA data;
 | 
			
		||||
        data.pSysMem          = info->data;
 | 
			
		||||
        data.SysMemPitch      = 0;
 | 
			
		||||
        data.SysMemSlicePitch = 0;
 | 
			
		||||
 | 
			
		||||
        if (FAILED(
 | 
			
		||||
                g_gpu.device->CreateBuffer(&desc, info[i].data ? &data : nullptr, &slot->buffer))) {
 | 
			
		||||
            rtLog("dx11", "Failed to create a deferred context.");
 | 
			
		||||
            auto lock_guard = rtAutoLock(_lock);
 | 
			
		||||
            for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                rt_buffer *s = &_buffers[p_buffers[j].index];
 | 
			
		||||
                s->next_free = _first_free;
 | 
			
		||||
                _first_free  = s;
 | 
			
		||||
            }
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        slot->version        = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
        const uint32_t index = (uint32_t)(slot - _buffers);
 | 
			
		||||
        p_buffers[i].version = slot->version;
 | 
			
		||||
        p_buffers[i].index   = index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        if (!RT_IS_HANDLE_VALID(buffers[i]) || (int)buffers[i].index >= rt_Dx11MaxBuffers.i)
 | 
			
		||||
            continue;
 | 
			
		||||
        auto lg = rtAutoLock(_lock);
 | 
			
		||||
        if (buffers[i].version != _buffers[buffers[i].index].version)
 | 
			
		||||
            continue;
 | 
			
		||||
        _buffers[buffers[i].index].buffer->Release();
 | 
			
		||||
        _buffers[buffers[i].index].next_free = _first_free;
 | 
			
		||||
        _first_free                          = &_buffers[buffers[i].index];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										140
									
								
								src/renderer/dx11/command_buffers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/renderer/dx11/command_buffers.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,140 @@
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
#include "runtime/threading.h"
 | 
			
		||||
#include "runtime/threading_helpers.hpp"
 | 
			
		||||
 | 
			
		||||
#include "device_objects.hpp"
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_Dx11MaxCommandBuffers,
 | 
			
		||||
          "Maximum number of simultaneously created command buffers. Default: 1024",
 | 
			
		||||
          1024);
 | 
			
		||||
 | 
			
		||||
static rt_command_buffer *_buffers;
 | 
			
		||||
static rt_command_buffer *_first_free;
 | 
			
		||||
static rt_mutex *_lock;
 | 
			
		||||
 | 
			
		||||
rt_result InitCommandBufferManagement() {
 | 
			
		||||
    _buffers = reinterpret_cast<rt_command_buffer *>(
 | 
			
		||||
        calloc((size_t)rt_Dx11MaxCommandBuffers.i, sizeof(rt_command_buffer)));
 | 
			
		||||
    if (!_buffers)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    _first_free = &_buffers[1];
 | 
			
		||||
 | 
			
		||||
    _lock = rtCreateMutex();
 | 
			
		||||
    if (!_lock) {
 | 
			
		||||
        free(_buffers);
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxCommandBuffers.i - 1; ++i) {
 | 
			
		||||
        _buffers[i].next_free = &_buffers[i + 1];
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownCommandBufferManagement() {
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxCommandBuffers.i; ++i) {
 | 
			
		||||
        if (_buffers[i].context)
 | 
			
		||||
            _buffers[i].context->Release();
 | 
			
		||||
    }
 | 
			
		||||
    free(_buffers);
 | 
			
		||||
    _buffers = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_result
 | 
			
		||||
RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count,
 | 
			
		||||
                                        const rt_alloc_command_buffer_info *,
 | 
			
		||||
                                        rt_command_buffer_handle *p_command_buffers) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        rtLockMutex(_lock);
 | 
			
		||||
        rt_command_buffer *slot = _first_free;
 | 
			
		||||
        if (slot)
 | 
			
		||||
            _first_free = slot->next_free;
 | 
			
		||||
        rtUnlockMutex(_lock);
 | 
			
		||||
 | 
			
		||||
        if (!slot) {
 | 
			
		||||
            rtLog("dx11", "Failed to allocate a command buffer slot.");
 | 
			
		||||
            rtLockMutex(_lock);
 | 
			
		||||
            for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                rt_command_buffer *s = &_buffers[p_command_buffers[j].index];
 | 
			
		||||
                s->next_free         = _first_free;
 | 
			
		||||
                _first_free          = s;
 | 
			
		||||
            }
 | 
			
		||||
            rtUnlockMutex(_lock);
 | 
			
		||||
            return RT_OUT_OF_MEMORY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!slot->context) {
 | 
			
		||||
            if (FAILED(g_gpu.device->CreateDeferredContext1(0, &slot->context))) {
 | 
			
		||||
                rtLog("dx11", "Failed to create a deferred context.");
 | 
			
		||||
                auto lock_guard = rtAutoLock(_lock);
 | 
			
		||||
                for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                    rt_command_buffer *s = &_buffers[p_command_buffers[j].index];
 | 
			
		||||
                    s->next_free         = _first_free;
 | 
			
		||||
                    _first_free          = s;
 | 
			
		||||
                }
 | 
			
		||||
                return RT_UNKNOWN_ERROR;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
            if (FAILED(slot->context->QueryInterface(IID_PPV_ARGS(&slot->annotation)))) {
 | 
			
		||||
                rtLog("dx11", "Failed to retrieve the annotation interface.");
 | 
			
		||||
                slot->annotation = nullptr;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
        } else {
 | 
			
		||||
            slot->context->ClearState();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        slot->version                = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
        const uint32_t index         = (uint32_t)(slot - _buffers);
 | 
			
		||||
        p_command_buffers[i].version = slot->version;
 | 
			
		||||
        p_command_buffers[i].index   = index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_result
 | 
			
		||||
RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue, const rt_submit_command_buffers_info *info) {
 | 
			
		||||
    // TODO: Handle semaphores
 | 
			
		||||
 | 
			
		||||
    // Submit the command lists to the gpu
 | 
			
		||||
    for (uint32_t i = 0; i < info->command_buffer_count; ++i) {
 | 
			
		||||
        rt_command_buffer *cmdbuf = &_buffers[info->command_buffers[i].index];
 | 
			
		||||
        if (cmdbuf->version != info->command_buffers[i].version) {
 | 
			
		||||
            rtLog("dx11", "Tried to submit an invalid command buffer (version mismatch)");
 | 
			
		||||
            return RT_INVALID_VALUE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ID3D11CommandList *cmdlist;
 | 
			
		||||
        if (FAILED(cmdbuf->context->FinishCommandList(FALSE, &cmdlist))) {
 | 
			
		||||
            rtLog("dx11", "FinishCommandList failed");
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rtLockMutex(g_gpu.context_lock);
 | 
			
		||||
        g_gpu.device_context->ExecuteCommandList(cmdlist, FALSE);
 | 
			
		||||
        rtUnlockMutex(g_gpu.context_lock);
 | 
			
		||||
 | 
			
		||||
        rtLockMutex(_lock);
 | 
			
		||||
        cmdbuf->next_free = _first_free;
 | 
			
		||||
        _first_free       = cmdbuf;
 | 
			
		||||
        rtUnlockMutex(_lock);
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_command_buffer *rtGetCommandBuffer(rt_command_buffer_handle handle) {
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxCommandBuffers.i)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    auto lg = rtAutoLock(_lock);
 | 
			
		||||
    if (handle.version != _buffers[handle.index].version)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    return &_buffers[handle.index];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										87
									
								
								src/renderer/dx11/commands.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/renderer/dx11/commands.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
 | 
			
		||||
#include "device_objects.hpp"
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmdhandle,
 | 
			
		||||
                                                 const rt_cmd_begin_pass_info *info) {
 | 
			
		||||
    rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle);
 | 
			
		||||
    if (!RT_VERIFY(cmd))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (cmd->annotation) {
 | 
			
		||||
        WCHAR wname[128];
 | 
			
		||||
        if (rtUTF8ToWStr(info->name, wname, sizeof(wname)) == RT_SUCCESS)
 | 
			
		||||
            cmd->annotation->BeginEvent(wname);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Setup rtvs
 | 
			
		||||
    ID3D11RenderTargetView *rtvs[4];
 | 
			
		||||
    ID3D11DepthStencilView *dsv = nullptr;
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < info->color_buffer_count; ++i) {
 | 
			
		||||
        rt_render_target *rt = rtGetRenderTarget(info->color_buffers[i]);
 | 
			
		||||
        if (!RT_VERIFY(rt))
 | 
			
		||||
            return;
 | 
			
		||||
        RT_ASSERT(rt->IsColorRenderTarget(), "Needs to provide a valid color render target");
 | 
			
		||||
        rtvs[i] = rt->rtv;
 | 
			
		||||
 | 
			
		||||
        if (info->color_buffer_loads[i] == RT_PASS_LOAD_MODE_CLEAR) {
 | 
			
		||||
            FLOAT color[4] = {
 | 
			
		||||
                info->color_buffer_clear_values[i].color.r,
 | 
			
		||||
                info->color_buffer_clear_values[i].color.g,
 | 
			
		||||
                info->color_buffer_clear_values[i].color.b,
 | 
			
		||||
                info->color_buffer_clear_values[i].color.a,
 | 
			
		||||
            };
 | 
			
		||||
            cmd->context->ClearRenderTargetView(rt->rtv, color);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_render_target *dsvrt = rtGetRenderTarget(info->depth_stencil_buffer);
 | 
			
		||||
    if (dsvrt) {
 | 
			
		||||
        RT_ASSERT(dsvrt->IsDepthStencilTarget(),
 | 
			
		||||
                  "Need to provide a valid depth stencil render target");
 | 
			
		||||
        dsv = dsvrt->dsv;
 | 
			
		||||
 | 
			
		||||
        if (info->depth_stencil_buffer_load == RT_PASS_LOAD_MODE_CLEAR)
 | 
			
		||||
            cmd->context->ClearDepthStencilView(
 | 
			
		||||
                dsv,
 | 
			
		||||
                (dsvrt->HasStencilComponent()) ? D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL
 | 
			
		||||
                                               : D3D11_CLEAR_DEPTH,
 | 
			
		||||
                info->depth_stencil_buffer_clear_value.depth_stencil.depth,
 | 
			
		||||
                static_cast<UINT8>(info->depth_stencil_buffer_clear_value.depth_stencil.stencil));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cmd->context->OMSetRenderTargets(static_cast<UINT>(info->color_buffer_count), rtvs, dsv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmdhandle) {
 | 
			
		||||
    rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle);
 | 
			
		||||
    if (!RT_VERIFY(cmd))
 | 
			
		||||
        return;
 | 
			
		||||
    if (cmd->annotation) {
 | 
			
		||||
        cmd->annotation->EndEvent();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdhandle,
 | 
			
		||||
                                                              rt_render_target_handle target,
 | 
			
		||||
                                                              rt_render_target_state state) {
 | 
			
		||||
    rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle);
 | 
			
		||||
    if (!RT_VERIFY(cmd))
 | 
			
		||||
        return;
 | 
			
		||||
    RT_UNUSED(target);
 | 
			
		||||
    RT_UNUSED(state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void
 | 
			
		||||
RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle cmdhandle,
 | 
			
		||||
                                              rt_render_target_handle render_target) {
 | 
			
		||||
    rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle);
 | 
			
		||||
    if (!RT_VERIFY(cmd))
 | 
			
		||||
        return;
 | 
			
		||||
    RT_UNUSED(render_target);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								src/renderer/dx11/device_objects.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/renderer/dx11/device_objects.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
#ifndef RT_DX11_DEVICE_OBJECTS_HPP
 | 
			
		||||
#define RT_DX11_DEVICE_OBJECTS_HPP
 | 
			
		||||
 | 
			
		||||
// Types containing various api objects
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "runtime/runtime.h"
 | 
			
		||||
 | 
			
		||||
struct rt_render_target {
 | 
			
		||||
    // Only one of these should be valid
 | 
			
		||||
    ID3D11RenderTargetView *rtv;
 | 
			
		||||
    ID3D11DepthStencilView *dsv;
 | 
			
		||||
 | 
			
		||||
    ID3D11Texture2D *texture;
 | 
			
		||||
 | 
			
		||||
    rt_pixel_format format;
 | 
			
		||||
 | 
			
		||||
    uint32_t version;
 | 
			
		||||
    rt_render_target *next_free;
 | 
			
		||||
 | 
			
		||||
    RT_INLINE bool HasStencilComponent() const {
 | 
			
		||||
        return format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RT_INLINE bool IsColorRenderTarget() const {
 | 
			
		||||
        RT_ASSERT(!(rtv != nullptr && dsv != nullptr),
 | 
			
		||||
                  "A render target should not contain a render target and a depth stencil view");
 | 
			
		||||
        return rtv != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RT_INLINE bool IsDepthStencilTarget() const {
 | 
			
		||||
        RT_ASSERT(!(rtv != nullptr && dsv != nullptr),
 | 
			
		||||
                  "A render target should not contain a render target and a depth stencil view");
 | 
			
		||||
        return dsv != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rt_command_buffer {
 | 
			
		||||
    // Only created once and then re-used.
 | 
			
		||||
    ID3D11DeviceContext1 *context;
 | 
			
		||||
    ID3DUserDefinedAnnotation *annotation;
 | 
			
		||||
 | 
			
		||||
    uint32_t version;
 | 
			
		||||
    rt_command_buffer *next_free;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rt_buffer {
 | 
			
		||||
    ID3D11Buffer *buffer;
 | 
			
		||||
    rt_buffer_type type;
 | 
			
		||||
    rt_buffer_usage usage;
 | 
			
		||||
 | 
			
		||||
    uint32_t version;
 | 
			
		||||
    rt_buffer *next_free;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rt_pipeline {
 | 
			
		||||
    ID3D11InputLayout *input_layout;
 | 
			
		||||
    ID3D11VertexShader *vertex_shader;
 | 
			
		||||
    ID3D11PixelShader *pixel_shader;
 | 
			
		||||
 | 
			
		||||
    ID3D11ComputeShader *compute_shader;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    rt_pipeline *next_free;
 | 
			
		||||
    uint32_t version;
 | 
			
		||||
 | 
			
		||||
    RT_INLINE bool IsComputePipeline() const {
 | 
			
		||||
        RT_ASSERT(!(compute_shader && (vertex_shader || pixel_shader)),
 | 
			
		||||
                  "A pipeline should contain either a compute shader or graphics shaders.");
 | 
			
		||||
        return compute_shader != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
rt_render_target *rtGetRenderTarget(rt_render_target_handle handle);
 | 
			
		||||
rt_command_buffer *rtGetCommandBuffer(rt_command_buffer_handle handle);
 | 
			
		||||
rt_buffer *rtGetBuffer(rt_buffer_handle handle);
 | 
			
		||||
rt_pipeline *rtGetPipeline(rt_pipeline_handle handle);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										41
									
								
								src/renderer/dx11/gpu.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/renderer/dx11/gpu.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
#ifndef RT_DX11_GPU_HPP
 | 
			
		||||
#define RT_DX11_GPU_HPP
 | 
			
		||||
 | 
			
		||||
#include <wrl.h>
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
#include <dxgi1_3.h>
 | 
			
		||||
 | 
			
		||||
#include "runtime/threading.h"
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
 | 
			
		||||
// Smart pointer for COM-Objects
 | 
			
		||||
template<typename T>
 | 
			
		||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
 | 
			
		||||
 | 
			
		||||
struct rt_swap_chain {
 | 
			
		||||
    ComPtr<IDXGISwapChain1> swap_chain;
 | 
			
		||||
    ComPtr<ID3D11RenderTargetView> rtv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct rt_gpu {
 | 
			
		||||
    ComPtr<ID3D11Device1> device;
 | 
			
		||||
    ComPtr<ID3D11DeviceContext1> device_context;
 | 
			
		||||
    ComPtr<IDXGIFactory2> dxgi_factory;
 | 
			
		||||
 | 
			
		||||
    rt_swap_chain swap_chain;
 | 
			
		||||
 | 
			
		||||
    rt_mutex *context_lock;
 | 
			
		||||
 | 
			
		||||
    D3D_FEATURE_LEVEL feature_level;
 | 
			
		||||
    D3D11_FEATURE_DATA_THREADING threading_support;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifndef DONT_DEFINE_GPU_GLOBAL
 | 
			
		||||
extern rt_gpu g_gpu;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
DXGI_FORMAT rtConvertPixelFormat(rt_pixel_format format);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										32
									
								
								src/renderer/dx11/helpers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/renderer/dx11/helpers.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
DXGI_FORMAT rtConvertPixelFormat(rt_pixel_format format) {
 | 
			
		||||
    switch (format) {
 | 
			
		||||
    case RT_PIXEL_FORMAT_INVALID:
 | 
			
		||||
        return DXGI_FORMAT_UNKNOWN;
 | 
			
		||||
    case RT_PIXEL_FORMAT_R8G8B8A8_UNORM:
 | 
			
		||||
        return DXGI_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
    case RT_PIXEL_FORMAT_B8G8R8A8_UNORM:
 | 
			
		||||
        return DXGI_FORMAT_B8G8R8A8_UNORM;
 | 
			
		||||
    case RT_PIXEL_FORMAT_R8G8B8A8_SRGB:
 | 
			
		||||
        return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
 | 
			
		||||
    case RT_PIXEL_FORMAT_B8G8R8A8_SRGB:
 | 
			
		||||
        return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
 | 
			
		||||
    case RT_PIXEL_FORMAT_R8G8B8_UNORM:
 | 
			
		||||
        return DXGI_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
    case RT_PIXEL_FORMAT_B8G8R8_UNORM:
 | 
			
		||||
        return DXGI_FORMAT_B8G8R8X8_UNORM;
 | 
			
		||||
    case RT_PIXEL_FORMAT_R8G8B8_SRGB:
 | 
			
		||||
        return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
 | 
			
		||||
    case RT_PIXEL_FORMAT_B8G8R8_SRGB:
 | 
			
		||||
        return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
 | 
			
		||||
 | 
			
		||||
    case RT_PIXEL_FORMAT_DEPTH24_STENCIL8:
 | 
			
		||||
        return DXGI_FORMAT_D24_UNORM_S8_UINT;
 | 
			
		||||
    case RT_PIXEL_FORMAT_DEPTH32:
 | 
			
		||||
        return DXGI_FORMAT_D32_FLOAT;
 | 
			
		||||
    
 | 
			
		||||
    default:
 | 
			
		||||
        return DXGI_FORMAT_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										283
									
								
								src/renderer/dx11/init.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								src/renderer/dx11/init.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,283 @@
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
#pragma warning Building DX11 on non - windows is probably a mistake
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <dxgi1_3.h>
 | 
			
		||||
#include <wrl.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
 | 
			
		||||
#define DONT_DEFINE_RENDERER_GLOBAL
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
RT_CVAR_S(
 | 
			
		||||
    rt_Dx11AdapterName,
 | 
			
		||||
    "Name of the adapter that should be used for device creation. Default: \"\" (Use default)",
 | 
			
		||||
    "");
 | 
			
		||||
RT_CVAR_I(rt_Dx11VSync, "Enable vsync. Default: 1", 1);
 | 
			
		||||
RT_CVAR_I(rt_Dx11MaxSubmittedCommandBuffers,
 | 
			
		||||
          "Maximum number of submitted command buffers per frame. Default: 1024",
 | 
			
		||||
          1024);
 | 
			
		||||
 | 
			
		||||
extern rt_cvar rt_Dx11MaxCommandBuffers;
 | 
			
		||||
 | 
			
		||||
rt_gpu g_gpu;
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(RegisterCVars)(void) {
 | 
			
		||||
    rtRegisterCVAR(&rt_Dx11AdapterName);
 | 
			
		||||
    rtRegisterCVAR(&rt_Dx11VSync);
 | 
			
		||||
    rtRegisterCVAR(&rt_Dx11MaxCommandBuffers);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static rt_swap_chain CreateSwapChain(HWND hwnd) {
 | 
			
		||||
    rt_swap_chain swc;
 | 
			
		||||
 | 
			
		||||
    DXGI_SWAP_CHAIN_DESC1 desc;
 | 
			
		||||
    desc.Width  = 0;                          // use window width
 | 
			
		||||
    desc.Height = 0;                          // use window height
 | 
			
		||||
    desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // can't specify _SRGB here when using
 | 
			
		||||
                                              // DXGI_SWAP_EFFECT_FLIP_* ...;
 | 
			
		||||
    desc.Stereo             = FALSE;
 | 
			
		||||
    desc.SampleDesc.Count   = 1;
 | 
			
		||||
    desc.SampleDesc.Quality = 0;
 | 
			
		||||
    desc.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 | 
			
		||||
    desc.BufferCount        = 2;
 | 
			
		||||
    desc.Scaling            = DXGI_SCALING_STRETCH;
 | 
			
		||||
    desc.SwapEffect         = DXGI_SWAP_EFFECT_FLIP_DISCARD;
 | 
			
		||||
    desc.AlphaMode          = DXGI_ALPHA_MODE_UNSPECIFIED;
 | 
			
		||||
    desc.Flags              = 0;
 | 
			
		||||
 | 
			
		||||
    if (FAILED(g_gpu.dxgi_factory->CreateSwapChainForHwnd(g_gpu.device.Get(),
 | 
			
		||||
                                                          hwnd,
 | 
			
		||||
                                                          &desc,
 | 
			
		||||
                                                          nullptr,
 | 
			
		||||
                                                          nullptr,
 | 
			
		||||
                                                          &swc.swap_chain))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to create the swap chain.");
 | 
			
		||||
        return swc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ID3D11Texture2D *frame_buffer;
 | 
			
		||||
    if (FAILED(swc.swap_chain->GetBuffer(0, IID_PPV_ARGS(&frame_buffer)))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to retrieve the backbuffer.");
 | 
			
		||||
        swc.swap_chain.Reset();
 | 
			
		||||
        return swc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
 | 
			
		||||
    rtv_desc.Format                        = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
 | 
			
		||||
    rtv_desc.ViewDimension                 = D3D11_RTV_DIMENSION_TEXTURE2D;
 | 
			
		||||
 | 
			
		||||
    if (FAILED(g_gpu.device->CreateRenderTargetView(frame_buffer, &rtv_desc, &swc.rtv))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to create the render target view for the backbuffer.");
 | 
			
		||||
        swc.swap_chain.Reset();
 | 
			
		||||
        return swc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return swc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static IDXGIAdapter *RetrieveSelectedAdapter(void) {
 | 
			
		||||
    ComPtr<IDXGIFactory2> factory;
 | 
			
		||||
    if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UINT i = 0;
 | 
			
		||||
    IDXGIAdapter *adapter;
 | 
			
		||||
    while (factory->EnumAdapters(i, &adapter) == S_OK) {
 | 
			
		||||
        ++i;
 | 
			
		||||
 | 
			
		||||
        DXGI_ADAPTER_DESC desc;
 | 
			
		||||
        adapter->GetDesc(&desc);
 | 
			
		||||
 | 
			
		||||
        char utf8_desc[256];
 | 
			
		||||
        rtWStrToUTF8(desc.Description, utf8_desc, 256);
 | 
			
		||||
 | 
			
		||||
        if (strncmp(utf8_desc, rt_Dx11AdapterName.s, 256) == 0)
 | 
			
		||||
            return adapter;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern rt_result InitCommandBufferManagement();
 | 
			
		||||
extern void ShutdownCommandBufferManagement();
 | 
			
		||||
extern rt_result InitRenderTargetManagement();
 | 
			
		||||
extern void ShutdownRenderTargetManagement();
 | 
			
		||||
extern rt_result InitBufferManagement();
 | 
			
		||||
extern void ShutdownBufferManagement();
 | 
			
		||||
 | 
			
		||||
extern "C" rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
 | 
			
		||||
    constexpr D3D_FEATURE_LEVEL feature_levels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
 | 
			
		||||
    UINT device_flags                            = 0;
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
    device_flags |= D3D11_CREATE_DEVICE_DEBUG;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    IDXGIAdapter *selected_adapter = RetrieveSelectedAdapter();
 | 
			
		||||
 | 
			
		||||
    ID3D11Device *base_device;
 | 
			
		||||
    ID3D11DeviceContext *base_context;
 | 
			
		||||
    if (FAILED(D3D11CreateDevice(selected_adapter,
 | 
			
		||||
                                 D3D_DRIVER_TYPE_HARDWARE,
 | 
			
		||||
                                 nullptr,
 | 
			
		||||
                                 device_flags,
 | 
			
		||||
                                 feature_levels,
 | 
			
		||||
                                 RT_ARRAY_COUNT(feature_levels),
 | 
			
		||||
                                 D3D11_SDK_VERSION,
 | 
			
		||||
                                 &base_device,
 | 
			
		||||
                                 &g_gpu.feature_level,
 | 
			
		||||
                                 &base_context))) {
 | 
			
		||||
        rtLog("dx11", "Feature level 11.1 creation failed, retrying with feature level 11.0");
 | 
			
		||||
        if (FAILED(D3D11CreateDevice(selected_adapter,
 | 
			
		||||
                                     D3D_DRIVER_TYPE_HARDWARE,
 | 
			
		||||
                                     nullptr,
 | 
			
		||||
                                     device_flags,
 | 
			
		||||
                                     &feature_levels[1],
 | 
			
		||||
                                     RT_ARRAY_COUNT(feature_levels) - 1,
 | 
			
		||||
                                     D3D11_SDK_VERSION,
 | 
			
		||||
                                     &base_device,
 | 
			
		||||
                                     &g_gpu.feature_level,
 | 
			
		||||
                                     &base_context))) {
 | 
			
		||||
            rtReportError("dx11", "Failed to create the d3d11 device.");
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (FAILED(base_device->QueryInterface(IID_PPV_ARGS(&g_gpu.device)))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to query the D3D11Device1 interface.");
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    if (FAILED(base_context->QueryInterface(IID_PPV_ARGS(&g_gpu.device_context)))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to query the D3D11DeviceContext1 interface.");
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IDXGIDevice1 *dxgi_device;
 | 
			
		||||
    if (FAILED(g_gpu.device->QueryInterface(&dxgi_device))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to query the DXGIDevice1 interface.");
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    IDXGIAdapter *adapter;
 | 
			
		||||
    if (FAILED(dxgi_device->GetAdapter(&adapter))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to retrieve the dxgi adapter.");
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    if (FAILED(adapter->GetParent(IID_PPV_ARGS(&g_gpu.dxgi_factory)))) {
 | 
			
		||||
        rtReportError("dx11", "Failed to retrieve the dxgi factory.");
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_gpu.device->CheckFeatureSupport(D3D11_FEATURE_THREADING,
 | 
			
		||||
                                      &g_gpu.threading_support,
 | 
			
		||||
                                      sizeof(g_gpu.threading_support));
 | 
			
		||||
 | 
			
		||||
    g_gpu.swap_chain = CreateSwapChain(info->hWnd);
 | 
			
		||||
 | 
			
		||||
    g_gpu.context_lock = rtCreateMutex();
 | 
			
		||||
 | 
			
		||||
    rt_result res = InitCommandBufferManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitRenderTargetManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitBufferManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(Shutdown)(void) {
 | 
			
		||||
    ShutdownBufferManagement();
 | 
			
		||||
    ShutdownRenderTargetManagement();
 | 
			
		||||
    ShutdownCommandBufferManagement();
 | 
			
		||||
    rtDestroyMutex(g_gpu.context_lock);
 | 
			
		||||
    g_gpu.swap_chain.rtv.Reset();
 | 
			
		||||
    g_gpu.swap_chain.swap_chain.Reset();
 | 
			
		||||
    g_gpu.dxgi_factory.Reset();
 | 
			
		||||
    g_gpu.device.Reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void) {
 | 
			
		||||
    // TODO: Verify this.
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(BeginFrame)(unsigned int frame_id) {
 | 
			
		||||
    RT_UNUSED(frame_id);
 | 
			
		||||
    FLOAT clear_color[4] = {
 | 
			
		||||
        0,
 | 
			
		||||
        0,
 | 
			
		||||
        0,
 | 
			
		||||
        0,
 | 
			
		||||
    };
 | 
			
		||||
    rtLockMutex(g_gpu.context_lock);
 | 
			
		||||
    g_gpu.device_context->ClearRenderTargetView(g_gpu.swap_chain.rtv.Get(), clear_color);
 | 
			
		||||
    rtUnlockMutex(g_gpu.context_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(EndFrame)(unsigned int frame_id) {
 | 
			
		||||
    RT_UNUSED(frame_id);
 | 
			
		||||
 | 
			
		||||
    rtLockMutex(g_gpu.context_lock);
 | 
			
		||||
    UINT sync_interval = rt_Dx11VSync.i ? 1 : 0;
 | 
			
		||||
    g_gpu.swap_chain.swap_chain->Present(sync_interval, 0);
 | 
			
		||||
    rtUnlockMutex(g_gpu.context_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copied from null. Delete once no longer needed
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_STUB2(type, initial)                                                         \
 | 
			
		||||
    static unsigned int s_next = (initial);                                                        \
 | 
			
		||||
    s_next                     = (s_next + 1) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX;                \
 | 
			
		||||
    type h                     = {                                                                 \
 | 
			
		||||
        1,                                                                     \
 | 
			
		||||
        s_next,                                                                \
 | 
			
		||||
    };                                                                         \
 | 
			
		||||
    return h;
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_STUB(type) RETURN_HANDLE_STUB2(type, 1)
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_ARRAY_STUB2(out, count, initial)                                             \
 | 
			
		||||
    static unsigned int s_next = (initial);                                                        \
 | 
			
		||||
    for (uint32_t i = 0; i < (count); ++i) {                                                       \
 | 
			
		||||
        (out)[i].index   = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX;                        \
 | 
			
		||||
        (out)[i].version = 1;                                                                      \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_ARRAY_STUB(out, count) RETURN_HANDLE_ARRAY_STUB2(out, count, 1)
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count,
 | 
			
		||||
                                               const rt_gpu_semaphore_info *info,
 | 
			
		||||
                                               rt_gpu_semaphore_handle *p_semaphores) {
 | 
			
		||||
    RT_UNUSED(info);
 | 
			
		||||
    RETURN_HANDLE_ARRAY_STUB2(p_semaphores, count, 3)
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(DestroySemaphores)(uint32_t count, rt_gpu_semaphore_handle *semaphores) {
 | 
			
		||||
    RT_UNUSED(count);
 | 
			
		||||
    RT_UNUSED(semaphores);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* NOTE(Kevin): It might become necessary to actually track the value, to correctly simulate gpu
 | 
			
		||||
 * behaviour */
 | 
			
		||||
uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle sem) {
 | 
			
		||||
    RT_UNUSED(sem);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void) {
 | 
			
		||||
    return {1, 1};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) {
 | 
			
		||||
    return {1, 2};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/renderer/dx11/meson.build
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/renderer/dx11/meson.build
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
if get_option('build_dx11')
 | 
			
		||||
    dx11_dep = declare_dependency(link_args: ['-ld3d11', '-ldxgi', '-lwinmm', '-ldxguid'])
 | 
			
		||||
 | 
			
		||||
    dx11_renderer_lib = library('rtdx11',
 | 
			
		||||
        # Project Sources
 | 
			
		||||
        'device_objects.hpp',
 | 
			
		||||
        'gpu.hpp',
 | 
			
		||||
 | 
			
		||||
        'buffers.cpp',
 | 
			
		||||
        'commands.cpp',
 | 
			
		||||
        'command_buffers.cpp',
 | 
			
		||||
        'helpers.cpp',
 | 
			
		||||
        'init.cpp',
 | 
			
		||||
        'render_targets.cpp',
 | 
			
		||||
 | 
			
		||||
        dependencies : [m_dep, windowing_dep, dx11_dep],
 | 
			
		||||
        include_directories : [engine_incdir, contrib_incdir],
 | 
			
		||||
        link_with : [runtime_lib],
 | 
			
		||||
        cpp_pch : 'pch/dx11_pch.h',
 | 
			
		||||
        override_options : ['b_sanitize=none'],
 | 
			
		||||
        install : true)
 | 
			
		||||
 | 
			
		||||
    engine_libs += dx11_renderer_lib
 | 
			
		||||
    engine_lib_paths += dx11_renderer_lib.full_path()
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										5
									
								
								src/renderer/dx11/pch/dx11_pch.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/renderer/dx11/pch/dx11_pch.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
// DX11 headers
 | 
			
		||||
#include <wrl.h>
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
#include <dxgi1_3.h>
 | 
			
		||||
							
								
								
									
										217
									
								
								src/renderer/dx11/pipelines.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/renderer/dx11/pipelines.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,217 @@
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/effect.h"
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
#include "runtime/mem_arena.h"
 | 
			
		||||
#include "runtime/threading_helpers.hpp"
 | 
			
		||||
 | 
			
		||||
#include "device_objects.hpp"
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_Dx11MaxPipelines,
 | 
			
		||||
          "Maximum number of simultaneously existing pipelines. Default: 128",
 | 
			
		||||
          128);
 | 
			
		||||
 | 
			
		||||
static rt_pipeline *_pipelines;
 | 
			
		||||
static rt_pipeline *_first_free;
 | 
			
		||||
static rt_mutex *_lock;
 | 
			
		||||
 | 
			
		||||
rt_result InitPipelineManagement() {
 | 
			
		||||
    _pipelines =
 | 
			
		||||
        reinterpret_cast<rt_pipeline *>(calloc((size_t)rt_Dx11MaxPipelines.i, sizeof(rt_pipeline)));
 | 
			
		||||
    if (!_pipelines)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
 | 
			
		||||
    _first_free = _pipelines + 1;
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxPipelines.i - 1; ++i)
 | 
			
		||||
        _pipelines[i].next_free = &_pipelines[i + 1];
 | 
			
		||||
 | 
			
		||||
    _lock = rtCreateMutex();
 | 
			
		||||
    if (!_lock) {
 | 
			
		||||
        free(_pipelines);
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownPipelineManagement() {
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxPipelines.i; ++i) {
 | 
			
		||||
        if (_pipelines[i].compute_shader)
 | 
			
		||||
            _pipelines[i].compute_shader->Release();
 | 
			
		||||
        if (_pipelines[i].vertex_shader)
 | 
			
		||||
            _pipelines[i].vertex_shader->Release();
 | 
			
		||||
        if (_pipelines[i].pixel_shader)
 | 
			
		||||
            _pipelines[i].pixel_shader->Release();
 | 
			
		||||
        if (_pipelines[i].input_layout)
 | 
			
		||||
            _pipelines[i].input_layout->Release();
 | 
			
		||||
    }
 | 
			
		||||
    free(_pipelines);
 | 
			
		||||
    rtDestroyMutex(_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_result GetShader(rt_resource_id id, rt_shader_info **p_shader, rt_arena *arena) {
 | 
			
		||||
    size_t shader_size = rtGetResourceSize(id);
 | 
			
		||||
    if (shader_size == 0)
 | 
			
		||||
        return RT_INVALID_VALUE;
 | 
			
		||||
    void *buffer = rtArenaPush(arena, shader_size);
 | 
			
		||||
    if (!buffer)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    rt_result res = rtGetResource(id, buffer);
 | 
			
		||||
    if (res != RT_SUCCESS) {
 | 
			
		||||
        rtArenaPop(arena, shader_size);
 | 
			
		||||
        return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_resource *resource = reinterpret_cast<rt_resource *>(buffer);
 | 
			
		||||
    RT_ASSERT(resource->type == RT_RESOURCE_SHADER, "Expected a shader");
 | 
			
		||||
    *p_shader = reinterpret_cast<rt_shader_info *>(resource->data);
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *info) {
 | 
			
		||||
    rt_pipeline *slot = nullptr;
 | 
			
		||||
    {
 | 
			
		||||
        auto lg = rtAutoLock(_lock);
 | 
			
		||||
 | 
			
		||||
        slot = _first_free;
 | 
			
		||||
        if (slot)
 | 
			
		||||
            _first_free = slot->next_free;
 | 
			
		||||
    }
 | 
			
		||||
    if (!slot) {
 | 
			
		||||
        rtLog("dx11", "Could not create pipeline, because no slots are available.");
 | 
			
		||||
        return RT_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
 | 
			
		||||
 | 
			
		||||
    if (info->vertex_shader != RT_INVALID_RESOURCE_ID) {
 | 
			
		||||
        rt_shader_info *vs;
 | 
			
		||||
        if (GetShader(info->vertex_shader, &vs, temp.arena) != RT_SUCCESS) {
 | 
			
		||||
            rtReportError("dx11", "Could not retrieve vertex shader data.");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void *bytecode = rtResolveRelptr(&vs->bytecode);
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateVertexShader(bytecode,
 | 
			
		||||
                                                    vs->bytecode_length,
 | 
			
		||||
                                                    NULL,
 | 
			
		||||
                                                    &slot->vertex_shader))) {
 | 
			
		||||
            rtReportError("dx11", "Vertex shader creation failed");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: effects should specify the expected vertex layout
 | 
			
		||||
        // For now, we use a default
 | 
			
		||||
        /* clang-format off */
 | 
			
		||||
        D3D11_INPUT_ELEMENT_DESC default_layout[] = {
 | 
			
		||||
            {"POSITION", 0,  DXGI_FORMAT_R32G32B32_FLOAT, 0,                            0, D3D11_INPUT_PER_VERTEX_DATA, 0},
 | 
			
		||||
            {"NORMAL",   0,  DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
 | 
			
		||||
            {"TANGENT",  0,  DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
 | 
			
		||||
            {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,     0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
 | 
			
		||||
        };
 | 
			
		||||
        /* clang-format on */
 | 
			
		||||
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateInputLayout(default_layout,
 | 
			
		||||
                                                   RT_ARRAY_COUNT(default_layout),
 | 
			
		||||
                                                   bytecode,
 | 
			
		||||
                                                   vs->bytecode_length,
 | 
			
		||||
                                                   &slot->input_layout))) {
 | 
			
		||||
            rtReportError("dx11", "Failed to create the vertex layout.");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (info->fragment_shader != RT_INVALID_RESOURCE_ID) {
 | 
			
		||||
        rt_shader_info *vs;
 | 
			
		||||
        if (GetShader(info->fragment_shader, &vs, temp.arena) != RT_SUCCESS) {
 | 
			
		||||
            rtReportError("dx11", "Could not retrieve fragment shader data.");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void *bytecode = rtResolveRelptr(&vs->bytecode);
 | 
			
		||||
        if (FAILED(g_gpu.device->CreatePixelShader(bytecode,
 | 
			
		||||
                                                   vs->bytecode_length,
 | 
			
		||||
                                                   NULL,
 | 
			
		||||
                                                   &slot->pixel_shader))) {
 | 
			
		||||
            rtReportError("dx11", "Fragment shader creation failed");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (info->compute_shader != RT_INVALID_RESOURCE_ID) {
 | 
			
		||||
        rt_shader_info *vs;
 | 
			
		||||
        if (GetShader(info->compute_shader, &vs, temp.arena) != RT_SUCCESS) {
 | 
			
		||||
            rtReportError("dx11", "Could not retrieve compute shader data.");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void *bytecode = rtResolveRelptr(&vs->bytecode);
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateComputeShader(bytecode,
 | 
			
		||||
                                                     vs->bytecode_length,
 | 
			
		||||
                                                     NULL,
 | 
			
		||||
                                                     &slot->compute_shader))) {
 | 
			
		||||
            rtReportError("dx11", "Compute shader creation failed");
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    slot->version  = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
    uint32_t index = static_cast<uint32_t>(slot - _pipelines);
 | 
			
		||||
    return {slot->version, index};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle) {
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxPipelines.i)
 | 
			
		||||
        return;
 | 
			
		||||
    auto lg = rtAutoLock(_lock);
 | 
			
		||||
    if (handle.version != _pipelines[handle.index].version)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (_pipelines[handle.index].compute_shader)
 | 
			
		||||
        _pipelines[handle.index].compute_shader->Release();
 | 
			
		||||
    if (_pipelines[handle.index].vertex_shader)
 | 
			
		||||
        _pipelines[handle.index].vertex_shader->Release();
 | 
			
		||||
    if (_pipelines[handle.index].pixel_shader)
 | 
			
		||||
        _pipelines[handle.index].pixel_shader->Release();
 | 
			
		||||
    if (_pipelines[handle.index].input_layout)
 | 
			
		||||
        _pipelines[handle.index].input_layout->Release();
 | 
			
		||||
 | 
			
		||||
    _pipelines[handle.index].next_free = _first_free;
 | 
			
		||||
    _pipelines[handle.index].version =
 | 
			
		||||
        (_pipelines[handle.index].version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
    _first_free = &_pipelines[handle.index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_pipeline *rtGetPipeline(rt_pipeline_handle handle) {
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxPipelines.i)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    auto lg = rtAutoLock(_lock);
 | 
			
		||||
    if (handle.version != _pipelines[handle.index].version)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    return &_pipelines[handle.index];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										173
									
								
								src/renderer/dx11/render_targets.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								src/renderer/dx11/render_targets.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,173 @@
 | 
			
		||||
#include <d3d11.h>
 | 
			
		||||
#include <d3d11_1.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
#include "runtime/threading_helpers.hpp"
 | 
			
		||||
 | 
			
		||||
#include "device_objects.hpp"
 | 
			
		||||
#include "gpu.hpp"
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_Dx11MaxRenderTargets,
 | 
			
		||||
          "Maximum number of simultaneously existing render targets. Default: 128",
 | 
			
		||||
          128);
 | 
			
		||||
 | 
			
		||||
static rt_render_target *_render_targets;
 | 
			
		||||
static rt_render_target *_first_free;
 | 
			
		||||
static rt_mutex *_lock;
 | 
			
		||||
 | 
			
		||||
rt_result InitRenderTargetManagement() {
 | 
			
		||||
    _render_targets = reinterpret_cast<rt_render_target *>(
 | 
			
		||||
        calloc((size_t)rt_Dx11MaxRenderTargets.i, sizeof(rt_render_target)));
 | 
			
		||||
    if (!_render_targets) {
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lock = rtCreateMutex();
 | 
			
		||||
    if (!_lock) {
 | 
			
		||||
        free(_render_targets);
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _render_targets[1].rtv     = g_gpu.swap_chain.rtv.Get();
 | 
			
		||||
    _render_targets[1].format  = RT_PIXEL_FORMAT_B8G8R8A8_SRGB;
 | 
			
		||||
    _render_targets[1].version = 1;
 | 
			
		||||
 | 
			
		||||
    _first_free = _render_targets + 2;
 | 
			
		||||
    for (int i = 0; i < rt_Dx11MaxRenderTargets.i; ++i) {
 | 
			
		||||
        _render_targets[i].next_free = &_render_targets[i + 1];
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownRenderTargetManagement() {
 | 
			
		||||
    // Swapchain rtv in slot 1 will be released elsewhere
 | 
			
		||||
    for (int i = 2; i < rt_Dx11MaxRenderTargets.i; ++i) {
 | 
			
		||||
        if (_render_targets[i].rtv)
 | 
			
		||||
            _render_targets[i].rtv->Release();
 | 
			
		||||
        if (_render_targets[i].dsv)
 | 
			
		||||
            _render_targets[i].dsv->Release();
 | 
			
		||||
        if (_render_targets[i].texture)
 | 
			
		||||
            _render_targets[i].texture->Release();
 | 
			
		||||
    }
 | 
			
		||||
    free(_render_targets);
 | 
			
		||||
    rtDestroyMutex(_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_render_target_handle
 | 
			
		||||
RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *info) {
 | 
			
		||||
    rt_render_target *slot = nullptr;
 | 
			
		||||
    {
 | 
			
		||||
        auto lock_guard = rtAutoLock(_lock);
 | 
			
		||||
        slot            = _first_free;
 | 
			
		||||
        _first_free     = slot->next_free;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!slot) {
 | 
			
		||||
        rtLog("dx11",
 | 
			
		||||
              "Could not create a new render target, because all available slots are currently in "
 | 
			
		||||
              "use.");
 | 
			
		||||
        return RT_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    slot->format = info->format;
 | 
			
		||||
 | 
			
		||||
    if (!rtIsDepthFormat(info->format)) {
 | 
			
		||||
        D3D11_TEXTURE2D_DESC tex_desc = {};
 | 
			
		||||
        tex_desc.Width                = info->width;
 | 
			
		||||
        tex_desc.Height               = info->height;
 | 
			
		||||
        tex_desc.MipLevels            = 1;
 | 
			
		||||
        tex_desc.ArraySize            = 1;
 | 
			
		||||
        tex_desc.Format               = rtConvertPixelFormat(info->format);
 | 
			
		||||
        tex_desc.SampleDesc.Count     = 1;
 | 
			
		||||
        tex_desc.SampleDesc.Quality   = 0;
 | 
			
		||||
        tex_desc.Usage                = D3D11_USAGE_DEFAULT; // read and write
 | 
			
		||||
        tex_desc.BindFlags            = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
 | 
			
		||||
        tex_desc.CPUAccessFlags       = 0; // none
 | 
			
		||||
        tex_desc.MiscFlags            = 0;
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateTexture2D(&tex_desc, nullptr, &slot->texture))) {
 | 
			
		||||
            rtLog("dx11", "Failed to create backing texture for render target %s", info->name);
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
 | 
			
		||||
        rtv_desc.Format                        = rtConvertPixelFormat(info->format);
 | 
			
		||||
        rtv_desc.ViewDimension                 = D3D11_RTV_DIMENSION_TEXTURE2D;
 | 
			
		||||
        rtv_desc.Texture2D.MipSlice            = 0;
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateRenderTargetView(slot->texture, &rtv_desc, &slot->rtv))) {
 | 
			
		||||
            slot->texture->Release();
 | 
			
		||||
            rtLog("dx11",
 | 
			
		||||
                  "Failed to create the render target view for render target %s",
 | 
			
		||||
                  info->name);
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        slot->version  = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
        uint32_t index = static_cast<uint32_t>(slot - _render_targets);
 | 
			
		||||
        return {.version = slot->version, .index = index};
 | 
			
		||||
    } else {
 | 
			
		||||
        D3D11_TEXTURE2D_DESC tex_desc = {};
 | 
			
		||||
        tex_desc.Width                = info->width;
 | 
			
		||||
        tex_desc.Height               = info->height;
 | 
			
		||||
        tex_desc.MipLevels            = 1;
 | 
			
		||||
        tex_desc.ArraySize            = 1;
 | 
			
		||||
        tex_desc.Format               = rtConvertPixelFormat(info->format);
 | 
			
		||||
        tex_desc.SampleDesc.Count     = 1;
 | 
			
		||||
        tex_desc.SampleDesc.Quality   = 0;
 | 
			
		||||
        tex_desc.Usage                = D3D11_USAGE_DEFAULT; // read and write
 | 
			
		||||
        tex_desc.BindFlags            = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
 | 
			
		||||
        tex_desc.CPUAccessFlags       = 0; // none
 | 
			
		||||
        tex_desc.MiscFlags            = 0;
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateTexture2D(&tex_desc, nullptr, &slot->texture))) {
 | 
			
		||||
            rtLog("dx11", "Failed to create backing texture for render target %s", info->name);
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
 | 
			
		||||
        dsv_desc.Format                        = rtConvertPixelFormat(info->format);
 | 
			
		||||
        dsv_desc.Flags                         = 0;
 | 
			
		||||
        dsv_desc.ViewDimension                 = D3D11_DSV_DIMENSION_TEXTURE2D;
 | 
			
		||||
        dsv_desc.Texture2D.MipSlice            = 0;
 | 
			
		||||
        if (FAILED(g_gpu.device->CreateDepthStencilView(slot->texture, &dsv_desc, &slot->dsv))) {
 | 
			
		||||
            slot->texture->Release();
 | 
			
		||||
            rtLog("dx11",
 | 
			
		||||
                  "Failed to create the depth stencil view for render target %s",
 | 
			
		||||
                  info->name);
 | 
			
		||||
            auto lg         = rtAutoLock(_lock);
 | 
			
		||||
            slot->next_free = _first_free;
 | 
			
		||||
            _first_free     = slot;
 | 
			
		||||
            return RT_INVALID_HANDLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        slot->version  = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
        uint32_t index = static_cast<uint32_t>(slot - _render_targets);
 | 
			
		||||
        return {.version = slot->version, .index = index};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" rt_render_target_handle RT_RENDERER_API_FN(GetSwapchainRenderTarget)(void) {
 | 
			
		||||
    return {1, 1};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" void RT_RENDERER_API_FN(DestroyRenderTarget)(rt_render_target_handle handle) {
 | 
			
		||||
    RT_UNUSED(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_render_target *rtGetRenderTarget(rt_render_target_handle handle) {
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxRenderTargets.i)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    auto lg = rtAutoLock(_lock);
 | 
			
		||||
    if (_render_targets[handle.index].version != handle.version)
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    return &_render_targets[handle.index];
 | 
			
		||||
}
 | 
			
		||||
@ -6,14 +6,14 @@
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_STUB2(type, initial)                                                         \
 | 
			
		||||
    static unsigned int s_next = (initial);                                                        \
 | 
			
		||||
    return (type) { .index = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX, .version = 1 }
 | 
			
		||||
    return (type) { .index = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX, .version = 1 }
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_STUB(type) RETURN_HANDLE_STUB2(type, 1)
 | 
			
		||||
 | 
			
		||||
#define RETURN_HANDLE_ARRAY_STUB2(out, count, initial)                                             \
 | 
			
		||||
    static unsigned int s_next = (initial);                                                        \
 | 
			
		||||
    for (uint32_t i = 0; i < (count); ++i) {                                                       \
 | 
			
		||||
        (out)[i].index   = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX;                      \
 | 
			
		||||
        (out)[i].index   = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX;                        \
 | 
			
		||||
        (out)[i].version = 1;                                                                      \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ runtime_lib = library('rt',
 | 
			
		||||
  'resources.h',
 | 
			
		||||
  'runtime.h',
 | 
			
		||||
  'threading.h',
 | 
			
		||||
  'threading_helpers.hpp',
 | 
			
		||||
  
 | 
			
		||||
  'aio.c',
 | 
			
		||||
  'assert.c',
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,9 @@
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wpedantic"
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#pragma warning(push)
 | 
			
		||||
#pragma warning(disable : 4201) /* anonymous struct */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct vec2 {
 | 
			
		||||
@ -44,6 +47,8 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -121,8 +121,18 @@ RT_DLLEXPORT int rtAssertHandler(const char *expr, const char *msg, const char *
 | 
			
		||||
            }                                                                                      \
 | 
			
		||||
        }                                                                                          \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
#define RT_ASSERT_ALWAYS_EVAL(x, msg) RT_ASSERT(x, msg)
 | 
			
		||||
 | 
			
		||||
// Asserts if p is "false", evaluates to p
 | 
			
		||||
// NOTE that this will evaluate p multiple times!
 | 
			
		||||
#define RT_VERIFY(p)                                                                               \
 | 
			
		||||
    ((!p) ? (RT_DEBUGBREAK, rtAssertHandler(#p, "Verify failed", __FILE__, __LINE__), p) : p)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#define RT_ASSERT(x, msg) RT_UNUSED(x)
 | 
			
		||||
#define RT_ASSERT(x, msg)             RT_UNUSED(x)
 | 
			
		||||
#define RT_ASSERT_ALWAYS_EVAL(x, msg) (x)
 | 
			
		||||
#define RT_VERIFY(p)                  (p)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								src/runtime/threading_helpers.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/runtime/threading_helpers.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
#ifndef RT_THREADING_HELPERS_HPP
 | 
			
		||||
#define RT_THREADING_HELPERS_HPP
 | 
			
		||||
 | 
			
		||||
// C++ wrappers around threading functions/types
 | 
			
		||||
 | 
			
		||||
#ifndef __cplusplus
 | 
			
		||||
#error This file must only be used from C++ code
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "threading.h"
 | 
			
		||||
 | 
			
		||||
template <typename _LockType, void (*_AcquireFunc)(_LockType *), void (*_ReleaseFunc)(_LockType *)>
 | 
			
		||||
class rt_generic_auto_lock {
 | 
			
		||||
  public:
 | 
			
		||||
    explicit rt_generic_auto_lock(_LockType *lock) : m_lock(lock) {
 | 
			
		||||
        _AcquireFunc(lock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~rt_generic_auto_lock() {
 | 
			
		||||
        _ReleaseFunc(m_lock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_generic_auto_lock(const rt_generic_auto_lock &)                  = delete;
 | 
			
		||||
    const rt_generic_auto_lock &operator=(const rt_generic_auto_lock &) = delete;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    _LockType *m_lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace __rt_auto_lock_mutex_wrappers {
 | 
			
		||||
 | 
			
		||||
RT_INLINE void Lock(rt_mutex *mtx) {
 | 
			
		||||
    RT_ASSERT_ALWAYS_EVAL(rtLockMutex(mtx), "Lock mutex failed!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_INLINE void Unlock(rt_mutex *mtx) {
 | 
			
		||||
    RT_ASSERT_ALWAYS_EVAL(rtUnlockMutex(mtx), "Unlock mutex failed!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace __rt_auto_lock_mutex_wrappers
 | 
			
		||||
 | 
			
		||||
using rt_mutex_auto_lock = rt_generic_auto_lock<rt_mutex,
 | 
			
		||||
                                          __rt_auto_lock_mutex_wrappers::Lock,
 | 
			
		||||
                                          __rt_auto_lock_mutex_wrappers::Unlock>;
 | 
			
		||||
 | 
			
		||||
using rt_read_auto_lock = rt_generic_auto_lock<rt_rwlock, rtLockRead, rtUnlockRead>;
 | 
			
		||||
using rt_write_auto_lock = rt_generic_auto_lock<rt_rwlock, rtLockWrite, rtUnlockWrite>;
 | 
			
		||||
 | 
			
		||||
RT_INLINE rt_mutex_auto_lock rtAutoLock(rt_mutex *mutex) {
 | 
			
		||||
    return rt_mutex_auto_lock(mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_INLINE rt_read_auto_lock rtAutoLock(rt_rwlock *rw) {
 | 
			
		||||
    return rt_read_auto_lock(rw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_INLINE rt_write_auto_lock rtAutoWriteLock(rt_rwlock *rw) {
 | 
			
		||||
    return rt_write_auto_lock(rw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user