Skip to content

Instantly share code, notes, and snippets.

@samloeschen
Created June 5, 2022 19:21
Show Gist options
  • Save samloeschen/70b9b8f90036db1345aa7e277bbd1e50 to your computer and use it in GitHub Desktop.
Save samloeschen/70b9b8f90036db1345aa7e277bbd1e50 to your computer and use it in GitHub Desktop.
d3d11 hello triangle in odin
package main
import "core:fmt"
import "vendor:directx/d3d11"
import "vendor:directx/d3d_compiler"
import "vendor:directx/dxgi"
import SDL "vendor:sdl2"
import "core:unicode/utf16"
WINDOW_WIDTH : i32 = 1280
WINDOW_HEIGHT : i32 = 720
SHADERS_PATH : string = "shaders.hlsl"
BACKGROUND := [4]f32 { 0.025, 0.025, 0.025, 1.0}
vertex_data := [?]f32 {
0.0, 0.5, 0.0, 1.0, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0, 0.0,
-0.5, -0.5, 0.0, 0.0, 0.0, 1.0,
}
VERTEX_STRIDE := u32(size_of(f32) * 6)
VERTEX_OFFSET := u32(0)
main :: proc () {
SDL.Init({ .VIDEO })
defer SDL.Quit()
SDL.SetHintWithPriority(SDL.HINT_RENDER_DRIVER, "direct3d11", SDL.HintPriority.OVERRIDE)
window_flags : SDL.WindowFlags = {.ALLOW_HIGHDPI, .HIDDEN, .RESIZABLE}
window := SDL.CreateWindow(
"Hello Triangle DX11",
SDL.WINDOWPOS_CENTERED,
SDL.WINDOWPOS_CENTERED,
WINDOW_WIDTH,
WINDOW_HEIGHT,
window_flags,
)
defer SDL.DestroyWindow(window)
window_system_info: SDL.SysWMinfo
SDL.GetVersion(&window_system_info.version)
SDL.GetWindowWMInfo(window, &window_system_info)
assert(window_system_info.subsystem == .WINDOWS)
native_window := dxgi.HWND(window_system_info.info.win.window)
base_device: ^d3d11.IDevice
base_device_ctx: ^d3d11.IDeviceContext
create_device_flags: d3d11.CREATE_DEVICE_FLAGS = {.BGRA_SUPPORT}
feature_levels := [1]d3d11.FEATURE_LEVEL{._11_0}
d3d11.CreateDevice(nil, .HARDWARE, nil, create_device_flags, &feature_levels[0], len(feature_levels), d3d11.SDK_VERSION, &base_device, nil, &base_device_ctx);
device: ^d3d11.IDevice
base_device->QueryInterface(d3d11.IDevice_UUID, (^rawptr)(&device))
device_ctx: ^d3d11.IDeviceContext
base_device_ctx->QueryInterface(d3d11.IDeviceContext_UUID, (^rawptr)(&device_ctx))
dxgi_device: ^dxgi.IDevice
device->QueryInterface(dxgi.IDevice_UUID, (^rawptr)(&dxgi_device))
dxgi_adapter: ^dxgi.IAdapter
dxgi_device->GetAdapter(&dxgi_adapter)
dxgi_factory: ^dxgi.IFactory2
dxgi_adapter->GetParent(dxgi.IFactory2_UUID, (^rawptr)(&dxgi_factory))
swapchain_desc := dxgi.SWAP_CHAIN_DESC1 {
Width = 0,
Height = 0, // use window width and height
Stereo = false,
Format = .B8G8R8A8_UNORM,
SampleDesc = dxgi.SAMPLE_DESC {
Count = 1,
Quality = 0,
},
BufferUsage = .RENDER_TARGET_OUTPUT,
BufferCount = 2,
Scaling = .STRETCH,
SwapEffect = .DISCARD,
AlphaMode = .UNSPECIFIED,
Flags = 0,
}
swapchain: ^dxgi.ISwapChain1
dxgi_factory->CreateSwapChainForHwnd(device, native_window, &swapchain_desc, nil, nil, &swapchain)
framebuffer: ^d3d11.ITexture2D
swapchain->GetBuffer(0, d3d11.ITexture2D_UUID, (^rawptr)(&framebuffer))
framebuffer_view: ^d3d11.IRenderTargetView
device->CreateRenderTargetView(framebuffer, nil, &framebuffer_view)
depth_buffer_desc: d3d11.TEXTURE2D_DESC
framebuffer->GetDesc(&depth_buffer_desc)
depth_buffer_desc.Format = .D24_UNORM_S8_UINT
depth_buffer_desc.BindFlags = .DEPTH_STENCIL
depth_buffer: ^d3d11.ITexture2D
device->CreateTexture2D(&depth_buffer_desc, nil, &depth_buffer)
// convert shaders path string to utf16
fpath := make([dynamic]u16, len(SHADERS_PATH))
utf16.encode_string(fpath[:], SHADERS_PATH)
vs_blob: ^d3d11.IBlob
d3d_compiler.CompileFromFile(&fpath[0], nil, nil, "vs_main", "vs_5_0", 0, 0, &vs_blob, nil)
assert(vs_blob != nil)
vertex_shader: ^d3d11.IVertexShader
device->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nil, &vertex_shader)
ps_blob: ^d3d11.IBlob
d3d_compiler.CompileFromFile(&fpath[0], nil, nil, "ps_main", "ps_5_0", 0, 0, &ps_blob, nil)
assert(ps_blob != nil)
pixel_shader: ^d3d11.IPixelShader
device->CreatePixelShader(ps_blob->GetBufferPointer(), ps_blob->GetBufferSize(), nil, &pixel_shader)
vertex_desc := [?]d3d11.INPUT_ELEMENT_DESC {
{ "POS", 0, .R32G32B32_FLOAT, 0, 0, .VERTEX_DATA, 0 },
{ "COL", 0, .R32G32B32_FLOAT, 0, d3d11.APPEND_ALIGNED_ELEMENT, .VERTEX_DATA, 0 },
}
input_layout: ^d3d11.IInputLayout
device->CreateInputLayout(&vertex_desc[0], len(vertex_desc), vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &input_layout)
rasterizer_desc := d3d11.RASTERIZER_DESC {
FillMode = .SOLID,
CullMode = .BACK,
}
rasterizer_state: ^d3d11.IRasterizerState
device->CreateRasterizerState(&rasterizer_desc, &rasterizer_state)
vertex_buffer_desc := d3d11.BUFFER_DESC {
ByteWidth = size_of(vertex_data),
Usage = .IMMUTABLE,
BindFlags = .VERTEX_BUFFER,
}
vertex_buffer: ^d3d11.IBuffer
device->CreateBuffer(
&vertex_buffer_desc,
&d3d11.SUBRESOURCE_DATA {
pSysMem = &vertex_data[0],
SysMemPitch = size_of(vertex_data),
},
&vertex_buffer,
)
SDL.ShowWindow(window)
for quit := false; !quit; {
for event: SDL.Event; SDL.PollEvent(&event) != 0; {
#partial switch (event.type) {
case SDL.EventType.QUIT:
quit = true
}
}
viewport := d3d11.VIEWPORT {
0, 0,
f32(depth_buffer_desc.Width),
f32(depth_buffer_desc.Height),
0, 1,
}
device_ctx->ClearRenderTargetView(framebuffer_view, &BACKGROUND)
device_ctx->IASetPrimitiveTopology(d3d11.PRIMITIVE_TOPOLOGY.TRIANGLELIST)
device_ctx->IASetInputLayout(input_layout)
stride := u32(size_of(f32) * 6)
offset := u32(0)
device_ctx->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset)
device_ctx->VSSetShader(vertex_shader, nil, 0)
device_ctx->RSSetViewports(1, &viewport)
device_ctx->RSSetState(rasterizer_state)
device_ctx->PSSetShader(pixel_shader, nil, 0)
device_ctx->OMSetRenderTargets(1, &framebuffer_view, nil)
device_ctx->Draw(3, 0)
swapchain->Present(1, 0)
}
}
struct vs_in {
float3 position : POS;
float3 color : COL;
};
struct vs_out {
float4 position : SV_POSITION;
float3 color : COL;
};
vs_out vs_main(vs_in input) {
vs_out output;
output.position = float4(input.position, 1.0);
output.color = input.color;
return output;
}
float4 ps_main(vs_out input) : SV_TARGET {
return float4(input.color, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment