backend_d3d11.odin 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  1. #+build windows
  2. package karl2d
  3. import win32 "core:sys/windows"
  4. import d3d11 "vendor:directx/d3d11"
  5. import dxgi "vendor:directx/dxgi"
  6. import "vendor:directx/d3d_compiler"
  7. import "core:strings"
  8. import "core:log"
  9. import "core:math/linalg"
  10. import "core:slice"
  11. import "core:mem"
  12. import "core:math"
  13. import "core:image"
  14. import hm "handle_map"
  15. import "base:runtime"
  16. import "core:image/bmp"
  17. import "core:image/png"
  18. import "core:image/tga"
  19. _ :: bmp
  20. _ :: png
  21. _ :: tga
  22. BACKEND_D3D11 :: Rendering_Backend {
  23. state_size = d3d11_state_size,
  24. init = d3d11_init,
  25. shutdown = d3d11_shutdown,
  26. clear = d3d11_clear,
  27. present = d3d11_present,
  28. draw_current_batch = d3d11_draw_current_batch,
  29. get_swapchain_width = d3d11_get_swapchain_width,
  30. get_swapchain_height = d3d11_get_swapchain_height,
  31. set_internal_state = d3d11_set_internal_state,
  32. }
  33. @(private="file")
  34. s: ^D3D11_State
  35. d3d11_state_size :: proc() -> int {
  36. return size_of(D3D11_State)
  37. }
  38. d3d11_init :: proc(state: rawptr, window_handle: uintptr, swapchain_width, swapchain_height: int,
  39. allocator := context.allocator, loc := #caller_location) {
  40. hwnd := win32.HWND(window_handle)
  41. s = (^D3D11_State)(state)
  42. s.allocator = allocator
  43. s.width = swapchain_width
  44. s.height = swapchain_height
  45. feature_levels := [?]d3d11.FEATURE_LEVEL{
  46. ._11_1,
  47. ._11_0,
  48. }
  49. base_device: ^d3d11.IDevice
  50. base_device_context: ^d3d11.IDeviceContext
  51. device_flags := d3d11.CREATE_DEVICE_FLAGS {
  52. .BGRA_SUPPORT,
  53. }
  54. when ODIN_DEBUG {
  55. device_flags += { .DEBUG }
  56. }
  57. ch(d3d11.CreateDevice(
  58. nil,
  59. .HARDWARE,
  60. nil,
  61. device_flags,
  62. &feature_levels[0], len(feature_levels),
  63. d3d11.SDK_VERSION, &base_device, nil, &base_device_context))
  64. ch(base_device->QueryInterface(d3d11.IInfoQueue_UUID, (^rawptr)(&s.info_queue)))
  65. ch(base_device->QueryInterface(d3d11.IDevice_UUID, (^rawptr)(&s.device)))
  66. ch(base_device_context->QueryInterface(d3d11.IDeviceContext_UUID, (^rawptr)(&s.device_context)))
  67. dxgi_device: ^dxgi.IDevice
  68. ch(s.device->QueryInterface(dxgi.IDevice_UUID, (^rawptr)(&dxgi_device)))
  69. base_device->Release()
  70. base_device_context->Release()
  71. dxgi_adapter: ^dxgi.IAdapter
  72. ch(dxgi_device->GetAdapter(&dxgi_adapter))
  73. dxgi_device->Release()
  74. dxgi_factory: ^dxgi.IFactory2
  75. ch(dxgi_adapter->GetParent(dxgi.IFactory2_UUID, (^rawptr)(&dxgi_factory)))
  76. swapchain_desc := dxgi.SWAP_CHAIN_DESC1 {
  77. Format = .B8G8R8A8_UNORM,
  78. SampleDesc = {
  79. Count = 1,
  80. },
  81. BufferUsage = {.RENDER_TARGET_OUTPUT},
  82. BufferCount = 2,
  83. Scaling = .STRETCH,
  84. SwapEffect = .DISCARD,
  85. }
  86. ch(dxgi_factory->CreateSwapChainForHwnd(s.device, hwnd, &swapchain_desc, nil, nil, &s.swapchain))
  87. ch(s.swapchain->GetBuffer(0, d3d11.ITexture2D_UUID, (^rawptr)(&s.framebuffer)))
  88. ch(s.device->CreateRenderTargetView(s.framebuffer, nil, &s.framebuffer_view))
  89. depth_buffer_desc: d3d11.TEXTURE2D_DESC
  90. s.framebuffer->GetDesc(&depth_buffer_desc)
  91. depth_buffer_desc.Format = .D24_UNORM_S8_UINT
  92. depth_buffer_desc.BindFlags = {.DEPTH_STENCIL}
  93. ch(s.device->CreateTexture2D(&depth_buffer_desc, nil, &s.depth_buffer))
  94. ch(s.device->CreateDepthStencilView(s.depth_buffer, nil, &s.depth_buffer_view))
  95. rasterizer_desc := d3d11.RASTERIZER_DESC{
  96. FillMode = .SOLID,
  97. CullMode = .BACK,
  98. }
  99. ch(s.device->CreateRasterizerState(&rasterizer_desc, &s.rasterizer_state))
  100. depth_stencil_desc := d3d11.DEPTH_STENCIL_DESC{
  101. DepthEnable = false,
  102. DepthWriteMask = .ALL,
  103. DepthFunc = .LESS,
  104. }
  105. ch(s.device->CreateDepthStencilState(&depth_stencil_desc, &s.depth_stencil_state))
  106. vertex_buffer_desc := d3d11.BUFFER_DESC{
  107. ByteWidth = VERTEX_BUFFER_MAX,
  108. Usage = .DYNAMIC,
  109. BindFlags = {.VERTEX_BUFFER},
  110. CPUAccessFlags = {.WRITE},
  111. }
  112. ch(s.device->CreateBuffer(&vertex_buffer_desc, nil, &s.vertex_buffer_gpu))
  113. s.vertex_buffer_cpu = make([]u8, VERTEX_BUFFER_MAX, allocator, loc)
  114. blend_desc := d3d11.BLEND_DESC {
  115. RenderTarget = {
  116. 0 = {
  117. BlendEnable = true,
  118. SrcBlend = .SRC_ALPHA,
  119. DestBlend = .INV_SRC_ALPHA,
  120. BlendOp = .ADD,
  121. SrcBlendAlpha = .ONE,
  122. DestBlendAlpha = .ZERO,
  123. BlendOpAlpha = .ADD,
  124. RenderTargetWriteMask = u8(d3d11.COLOR_WRITE_ENABLE_ALL),
  125. },
  126. },
  127. }
  128. ch(s.device->CreateBlendState(&blend_desc, &s.blend_state))
  129. s.proj_matrix = make_default_projection(swapchain_width, swapchain_height)
  130. s.view_matrix = 1
  131. sampler_desc := d3d11.SAMPLER_DESC{
  132. Filter = .MIN_MAG_MIP_POINT,
  133. AddressU = .WRAP,
  134. AddressV = .WRAP,
  135. AddressW = .WRAP,
  136. ComparisonFunc = .NEVER,
  137. }
  138. s.device->CreateSamplerState(&sampler_desc, &s.sampler_state)
  139. s.default_shader = _load_shader(string(shader_hlsl), {
  140. .RG32_Float,
  141. .RG32_Float,
  142. .RGBA8_Norm,
  143. })
  144. white_rect: [16*16*4]u8
  145. slice.fill(white_rect[:], 255)
  146. s.shape_drawing_texture = _load_texture_from_memory(white_rect[:], 16, 16)
  147. }
  148. d3d11_shutdown :: proc() {
  149. _destroy_texture(s.shape_drawing_texture)
  150. _destroy_shader(s.default_shader)
  151. s.sampler_state->Release()
  152. s.framebuffer_view->Release()
  153. s.depth_buffer_view->Release()
  154. s.depth_buffer->Release()
  155. s.framebuffer->Release()
  156. s.device_context->Release()
  157. s.vertex_buffer_gpu->Release()
  158. //s.constant_buffer->Release()
  159. s.depth_stencil_state->Release()
  160. s.rasterizer_state->Release()
  161. s.swapchain->Release()
  162. s.blend_state->Release()
  163. delete(s.vertex_buffer_cpu, s.allocator)
  164. when ODIN_DEBUG {
  165. debug: ^d3d11.IDebug
  166. if ch(s.device->QueryInterface(d3d11.IDebug_UUID, (^rawptr)(&debug))) >= 0 {
  167. ch(debug->ReportLiveDeviceObjects({.DETAIL, .IGNORE_INTERNAL}))
  168. log_messages()
  169. }
  170. debug->Release()
  171. }
  172. s.device->Release()
  173. s.info_queue->Release()
  174. }
  175. d3d11_set_internal_state :: proc(state: rawptr) {
  176. s = (^D3D11_State)(state)
  177. }
  178. d3d11_get_swapchain_width :: proc() -> int {
  179. return s.width
  180. }
  181. d3d11_get_swapchain_height :: proc() -> int {
  182. return s.height
  183. }
  184. shader_hlsl :: #load("shader.hlsl")
  185. VERTEX_BUFFER_MAX :: 1000000
  186. Handle :: hm.Handle
  187. Texture_Handle :: distinct hm.Handle
  188. TEXTURE_NONE :: Texture_Handle {}
  189. Shader_Constant_Buffer :: struct {
  190. gpu_data: ^d3d11.IBuffer,
  191. cpu_data: []u8,
  192. }
  193. Shader_Builtin_Constant :: enum {
  194. MVP,
  195. }
  196. Shader_Input_Type :: enum {
  197. F32,
  198. Vec2,
  199. Vec3,
  200. Vec4,
  201. }
  202. Shader_Input :: struct {
  203. name: string,
  204. register: int,
  205. type: Shader_Input_Type,
  206. format: Shader_Input_Format,
  207. }
  208. Shader_Default_Inputs :: enum {
  209. Position,
  210. UV,
  211. Color,
  212. }
  213. Shader :: struct {
  214. handle: Shader_Handle,
  215. vertex_shader: ^d3d11.IVertexShader,
  216. pixel_shader: ^d3d11.IPixelShader,
  217. input_layout: ^d3d11.IInputLayout,
  218. constant_buffers: []Shader_Constant_Buffer,
  219. constant_lookup: map[string]Shader_Constant_Location,
  220. constant_builtin_locations: [Shader_Builtin_Constant]Maybe(Shader_Constant_Location),
  221. inputs: []Shader_Input,
  222. input_overrides: []Shader_Input_Value_Override,
  223. default_input_offsets: [Shader_Default_Inputs]int,
  224. vertex_size: int,
  225. }
  226. D3D11_State :: struct {
  227. allocator: runtime.Allocator,
  228. width: int,
  229. height: int,
  230. swapchain: ^dxgi.ISwapChain1,
  231. framebuffer_view: ^d3d11.IRenderTargetView,
  232. depth_buffer_view: ^d3d11.IDepthStencilView,
  233. device_context: ^d3d11.IDeviceContext,
  234. depth_stencil_state: ^d3d11.IDepthStencilState,
  235. rasterizer_state: ^d3d11.IRasterizerState,
  236. device: ^d3d11.IDevice,
  237. depth_buffer: ^d3d11.ITexture2D,
  238. framebuffer: ^d3d11.ITexture2D,
  239. blend_state: ^d3d11.IBlendState,
  240. shape_drawing_texture: Texture,
  241. sampler_state: ^d3d11.ISamplerState,
  242. default_shader: Shader_Handle,
  243. textures: hm.Handle_Map(_Texture, Texture_Handle, 1024*10),
  244. shaders: hm.Handle_Map(Shader, Shader_Handle, 1024*10),
  245. info_queue: ^d3d11.IInfoQueue,
  246. vertex_buffer_gpu: ^d3d11.IBuffer,
  247. vertex_buffer_cpu: []u8,
  248. vertex_buffer_cpu_used: int,
  249. vertex_buffer_offset: int,
  250. batch_texture: Texture_Handle,
  251. batch_camera: Maybe(Camera),
  252. batch_shader: Shader_Handle,
  253. view_matrix: matrix[4,4]f32,
  254. proj_matrix: matrix[4,4]f32,
  255. }
  256. Color_F32 :: [4]f32
  257. f32_color_from_color :: proc(color: Color) -> Color_F32 {
  258. return {
  259. f32(color.r) / 255,
  260. f32(color.g) / 255,
  261. f32(color.b) / 255,
  262. f32(color.a) / 255,
  263. }
  264. }
  265. d3d11_clear :: proc(color: Color) {
  266. c := f32_color_from_color(color)
  267. s.device_context->ClearRenderTargetView(s.framebuffer_view, &c)
  268. s.device_context->ClearDepthStencilView(s.depth_buffer_view, {.DEPTH}, 1, 0)
  269. }
  270. _Texture :: struct {
  271. handle: Texture_Handle,
  272. tex: ^d3d11.ITexture2D,
  273. view: ^d3d11.IShaderResourceView,
  274. }
  275. _load_texture_from_file :: proc(filename: string) -> Texture {
  276. img, img_err := image.load_from_file(filename, options = {.alpha_add_if_missing}, allocator = context.temp_allocator)
  277. if img_err != nil {
  278. log.errorf("Error loading texture %v: %v", filename, img_err)
  279. return {}
  280. }
  281. return _load_texture_from_memory(img.pixels.buf[:], img.width, img.height)
  282. }
  283. _load_texture_from_memory :: proc(data: []u8, width: int, height: int) -> Texture {
  284. texture_desc := d3d11.TEXTURE2D_DESC{
  285. Width = u32(width),
  286. Height = u32(height),
  287. MipLevels = 1,
  288. ArraySize = 1,
  289. // TODO: _SRGB or not?
  290. Format = .R8G8B8A8_UNORM,
  291. SampleDesc = {Count = 1},
  292. Usage = .IMMUTABLE,
  293. BindFlags = {.SHADER_RESOURCE},
  294. }
  295. texture_data := d3d11.SUBRESOURCE_DATA{
  296. pSysMem = raw_data(data),
  297. SysMemPitch = u32(width * 4),
  298. }
  299. texture: ^d3d11.ITexture2D
  300. s.device->CreateTexture2D(&texture_desc, &texture_data, &texture)
  301. texture_view: ^d3d11.IShaderResourceView
  302. s.device->CreateShaderResourceView(texture, nil, &texture_view)
  303. tex := _Texture {
  304. tex = texture,
  305. view = texture_view,
  306. }
  307. handle := hm.add(&s.textures, tex)
  308. return {
  309. id = handle,
  310. width = width,
  311. height = height,
  312. }
  313. }
  314. _destroy_texture :: proc(tex: Texture) {
  315. if t := hm.get(&s.textures, tex.id); t != nil {
  316. t.tex->Release()
  317. t.view->Release()
  318. }
  319. hm.remove(&s.textures, tex.id)
  320. }
  321. _draw_texture :: proc(tex: Texture, pos: Vec2, tint := WHITE) {
  322. _draw_texture_ex(
  323. tex,
  324. {0, 0, f32(tex.width), f32(tex.height)},
  325. {pos.x, pos.y, f32(tex.width), f32(tex.height)},
  326. {},
  327. 0,
  328. tint,
  329. )
  330. }
  331. _draw_texture_rect :: proc(tex: Texture, rect: Rect, pos: Vec2, tint := WHITE) {
  332. _draw_texture_ex(
  333. tex,
  334. rect,
  335. {pos.x, pos.y, rect.w, rect.h},
  336. {},
  337. 0,
  338. tint,
  339. )
  340. }
  341. Shader_Input_Value_Override :: struct {
  342. val: [256]u8,
  343. used: int,
  344. }
  345. create_vertex_input_override :: proc(val: $T) -> Shader_Input_Value_Override {
  346. assert(size_of(T) < 256)
  347. res: Shader_Input_Value_Override
  348. ((^T)(raw_data(&res.val)))^ = val
  349. res.used = size_of(T)
  350. return res
  351. }
  352. set_vertex_input_override :: proc(shader: Shader_Handle, input_idx: int, override: Shader_Input_Value_Override) {
  353. shd := hm.get(&s.shaders, shader)
  354. if shd == nil {
  355. log.error("Valid shader")
  356. return
  357. }
  358. if input_idx < 0 || input_idx >= len(shd.input_overrides) {
  359. log.error("Override input idx out of bounds")
  360. return
  361. }
  362. shd.input_overrides[input_idx] = override
  363. }
  364. batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
  365. v := v
  366. if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
  367. panic("Must dispatch here")
  368. }
  369. shd := hm.get(&s.shaders, s.batch_shader)
  370. if shd == nil {
  371. shd = hm.get(&s.shaders, s.default_shader)
  372. assert(shd != nil, "Failed fetching default shader")
  373. }
  374. base_offset := s.vertex_buffer_cpu_used
  375. pos_offset := shd.default_input_offsets[.Position]
  376. uv_offset := shd.default_input_offsets[.UV]
  377. color_offset := shd.default_input_offsets[.Color]
  378. if pos_offset != -1 {
  379. (^Vec2)(&s.vertex_buffer_cpu[base_offset + pos_offset])^ = v
  380. }
  381. if uv_offset != -1 {
  382. (^Vec2)(&s.vertex_buffer_cpu[base_offset + uv_offset])^ = uv
  383. }
  384. if color_offset != -1 {
  385. (^Color)(&s.vertex_buffer_cpu[base_offset + color_offset])^ = color
  386. }
  387. override_offset: int
  388. for &o, idx in shd.input_overrides {
  389. input := &shd.inputs[idx]
  390. sz := shader_input_format_size(input.format)
  391. if o.used != 0 {
  392. mem.copy(&s.vertex_buffer_cpu[base_offset + override_offset], raw_data(&o.val), o.used)
  393. }
  394. override_offset += sz
  395. }
  396. s.vertex_buffer_cpu_used += shd.vertex_size
  397. }
  398. _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot: f32, tint := WHITE) {
  399. if tex.width == 0 || tex.height == 0 {
  400. return
  401. }
  402. if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.id {
  403. d3d11_draw_current_batch()
  404. }
  405. r := dst
  406. r.x -= origin.x
  407. r.y -= origin.y
  408. s.batch_texture = tex.id
  409. tl, tr, bl, br: Vec2
  410. // Rotation adapted from Raylib's "DrawTexturePro"
  411. if rot == 0 {
  412. x := dst.x - origin.x
  413. y := dst.y - origin.y
  414. tl = { x, y }
  415. tr = { x + dst.w, y }
  416. bl = { x, y + dst.h }
  417. br = { x + dst.w, y + dst.h }
  418. } else {
  419. sin_rot := math.sin(rot * math.RAD_PER_DEG)
  420. cos_rot := math.cos(rot * math.RAD_PER_DEG)
  421. x := dst.x
  422. y := dst.y
  423. dx := -origin.x
  424. dy := -origin.y
  425. tl = {
  426. x + dx * cos_rot - dy * sin_rot,
  427. y + dx * sin_rot + dy * cos_rot,
  428. }
  429. tr = {
  430. x + (dx + dst.w) * cos_rot - dy * sin_rot,
  431. y + (dx + dst.w) * sin_rot + dy * cos_rot,
  432. }
  433. bl = {
  434. x + dx * cos_rot - (dy + dst.h) * sin_rot,
  435. y + dx * sin_rot + (dy + dst.h) * cos_rot,
  436. }
  437. br = {
  438. x + (dx + dst.w) * cos_rot - (dy + dst.h) * sin_rot,
  439. y + (dx + dst.w) * sin_rot + (dy + dst.h) * cos_rot,
  440. }
  441. }
  442. ts := Vec2{f32(tex.width), f32(tex.height)}
  443. up := Vec2{src.x, src.y} / ts
  444. us := Vec2{src.w, src.h} / ts
  445. c := tint
  446. batch_vertex(tl, up, c)
  447. batch_vertex(tr, up + {us.x, 0}, c)
  448. batch_vertex(br, up + us, c)
  449. batch_vertex(tl, up, c)
  450. batch_vertex(br, up + us, c)
  451. batch_vertex(bl, up + {0, us.y}, c)
  452. }
  453. _draw_rectangle :: proc(r: Rect, c: Color) {
  454. if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture.id {
  455. d3d11_draw_current_batch()
  456. }
  457. s.batch_texture = s.shape_drawing_texture.id
  458. batch_vertex({r.x, r.y}, {0, 0}, c)
  459. batch_vertex({r.x + r.w, r.y}, {1, 0}, c)
  460. batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  461. batch_vertex({r.x, r.y}, {0, 0}, c)
  462. batch_vertex({r.x + r.w, r.y + r.h}, {1, 1}, c)
  463. batch_vertex({r.x, r.y + r.h}, {0, 1}, c)
  464. }
  465. _draw_rectangle_outline :: proc(r: Rect, thickness: f32, color: Color) {
  466. t := thickness
  467. // Based on DrawRectangleLinesEx from Raylib
  468. top := Rect {
  469. r.x,
  470. r.y,
  471. r.w,
  472. t,
  473. }
  474. bottom := Rect {
  475. r.x,
  476. r.y + r.h - t,
  477. r.w,
  478. t,
  479. }
  480. left := Rect {
  481. r.x,
  482. r.y + t,
  483. t,
  484. r.h - t * 2,
  485. }
  486. right := Rect {
  487. r.x + r.w - t,
  488. r.y + t,
  489. t,
  490. r.h - t * 2,
  491. }
  492. _draw_rectangle(top, color)
  493. _draw_rectangle(bottom, color)
  494. _draw_rectangle(left, color)
  495. _draw_rectangle(right, color)
  496. }
  497. _draw_circle :: proc(center: Vec2, radius: f32, color: Color) {
  498. }
  499. _draw_line :: proc(start: Vec2, end: Vec2, thickness: f32, color: Color) {
  500. }
  501. _get_default_shader :: proc() -> Shader_Handle {
  502. return s.default_shader
  503. }
  504. _draw_text :: proc(text: string, pos: Vec2, font_size: f32, color: Color) {
  505. }
  506. _mouse_button_pressed :: proc(button: Mouse_Button) -> bool {
  507. return false
  508. }
  509. _mouse_button_released :: proc(button: Mouse_Button) -> bool {
  510. return false
  511. }
  512. _mouse_button_held :: proc(button: Mouse_Button) -> bool {
  513. return false
  514. }
  515. _mouse_wheel_delta :: proc() -> f32 {
  516. return 0
  517. }
  518. _mouse_position :: proc() -> Vec2 {
  519. return {}
  520. }
  521. _enable_scissor :: proc(x, y, w, h: int) {
  522. }
  523. _disable_scissor :: proc() {
  524. }
  525. _set_window_size :: proc(width: int, height: int) {
  526. }
  527. _screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2 {
  528. return pos
  529. }
  530. Vec3 :: [3]f32
  531. vec3_from_vec2 :: proc(v: Vec2) -> Vec3 {
  532. return {
  533. v.x, v.y, 0,
  534. }
  535. }
  536. _set_camera :: proc(camera: Maybe(Camera)) {
  537. if camera == s.batch_camera {
  538. return
  539. }
  540. d3d11_draw_current_batch()
  541. s.batch_camera = camera
  542. if c, c_ok := camera.?; c_ok {
  543. origin_trans := linalg.matrix4_translate(vec3_from_vec2(-c.origin))
  544. translate := linalg.matrix4_translate(vec3_from_vec2(c.target))
  545. rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
  546. camera_matrix := translate * rot * origin_trans
  547. s.view_matrix = linalg.inverse(camera_matrix)
  548. s.proj_matrix = make_default_projection(s.width, s.height)
  549. s.proj_matrix[0, 0] *= c.zoom
  550. s.proj_matrix[1, 1] *= c.zoom
  551. } else {
  552. s.proj_matrix = make_default_projection(s.width, s.height)
  553. s.view_matrix = 1
  554. }
  555. }
  556. _set_scissor_rect :: proc(scissor_rect: Maybe(Rect)) {
  557. }
  558. _set_shader :: proc(shader: Shader_Handle) {
  559. if shader == s.batch_shader {
  560. return
  561. }
  562. d3d11_draw_current_batch()
  563. s.batch_shader = shader
  564. }
  565. _set_shader_constant :: proc(shader: Shader_Handle, loc: Shader_Constant_Location, val: $T) {
  566. d3d11_draw_current_batch()
  567. shd := hm.get(&s.shaders, shader)
  568. if shd == nil {
  569. return
  570. }
  571. if int(loc.buffer_idx) >= len(shd.constant_buffers) {
  572. log.warnf("Constant buffer idx %v is out of bounds", loc.buffer_idx)
  573. return
  574. }
  575. b := &shd.constant_buffers[loc.buffer_idx]
  576. if int(loc.offset) + size_of(val) > len(b.cpu_data) {
  577. log.warnf("Constant buffer idx %v is trying to be written out of bounds by at offset %v with %v bytes", loc.buffer_idx, loc.offset, size_of(val))
  578. return
  579. }
  580. dst := (^T)(&b.cpu_data[loc.offset])
  581. dst^ = val
  582. }
  583. _set_shader_constant_mat4 :: proc(shader: Shader_Handle, loc: Shader_Constant_Location, val: matrix[4,4]f32) {
  584. _set_shader_constant(shader, loc, val)
  585. }
  586. _set_shader_constant_f32 :: proc(shader: Shader_Handle, loc: Shader_Constant_Location, val: f32) {
  587. _set_shader_constant(shader, loc, val)
  588. }
  589. _set_shader_constant_vec2 :: proc(shader: Shader_Handle, loc: Shader_Constant_Location, val: Vec2) {
  590. _set_shader_constant(shader, loc, val)
  591. }
  592. d3d11_draw_current_batch :: proc() {
  593. if s.vertex_buffer_cpu_used == s.vertex_buffer_offset {
  594. return
  595. }
  596. viewport := d3d11.VIEWPORT{
  597. 0, 0,
  598. f32(s.width), f32(s.height),
  599. 0, 1,
  600. }
  601. dc := s.device_context
  602. vb_data: d3d11.MAPPED_SUBRESOURCE
  603. ch(dc->Map(s.vertex_buffer_gpu, 0, .WRITE_NO_OVERWRITE, {}, &vb_data))
  604. {
  605. gpu_map := slice.from_ptr((^u8)(vb_data.pData), VERTEX_BUFFER_MAX)
  606. copy(
  607. gpu_map[s.vertex_buffer_offset:s.vertex_buffer_cpu_used],
  608. s.vertex_buffer_cpu[s.vertex_buffer_offset:s.vertex_buffer_cpu_used],
  609. )
  610. }
  611. dc->Unmap(s.vertex_buffer_gpu, 0)
  612. dc->IASetPrimitiveTopology(.TRIANGLELIST)
  613. shd := hm.get(&s.shaders, s.batch_shader)
  614. if shd == nil {
  615. shd = hm.get(&s.shaders, s.default_shader)
  616. assert(shd != nil, "Failed fetching default shader")
  617. }
  618. dc->IASetInputLayout(shd.input_layout)
  619. vertex_buffer_offset := u32(0)
  620. vertex_buffer_stride := u32(shd.vertex_size)
  621. dc->IASetVertexBuffers(0, 1, &s.vertex_buffer_gpu, &vertex_buffer_stride, &vertex_buffer_offset)
  622. for mloc, builtin in shd.constant_builtin_locations {
  623. loc, loc_ok := mloc.?
  624. if !loc_ok {
  625. continue
  626. }
  627. switch builtin {
  628. case .MVP:
  629. dst := (^matrix[4,4]f32)(&shd.constant_buffers[loc.buffer_idx].cpu_data[loc.offset])
  630. dst^ = s.proj_matrix * s.view_matrix
  631. }
  632. }
  633. dc->VSSetShader(shd.vertex_shader, nil, 0)
  634. for &c, c_idx in shd.constant_buffers {
  635. if c.gpu_data == nil {
  636. continue
  637. }
  638. cb_data: d3d11.MAPPED_SUBRESOURCE
  639. ch(dc->Map(c.gpu_data, 0, .WRITE_DISCARD, {}, &cb_data))
  640. mem.copy(cb_data.pData, raw_data(c.cpu_data), len(c.cpu_data))
  641. dc->Unmap(c.gpu_data, 0)
  642. dc->VSSetConstantBuffers(u32(c_idx), 1, &c.gpu_data)
  643. dc->PSSetConstantBuffers(u32(c_idx), 1, &c.gpu_data)
  644. }
  645. dc->RSSetViewports(1, &viewport)
  646. dc->RSSetState(s.rasterizer_state)
  647. dc->PSSetShader(shd.pixel_shader, nil, 0)
  648. if t := hm.get(&s.textures, s.batch_texture); t != nil {
  649. dc->PSSetShaderResources(0, 1, &t.view)
  650. }
  651. dc->PSSetSamplers(0, 1, &s.sampler_state)
  652. dc->OMSetRenderTargets(1, &s.framebuffer_view, s.depth_buffer_view)
  653. dc->OMSetDepthStencilState(s.depth_stencil_state, 0)
  654. dc->OMSetBlendState(s.blend_state, nil, ~u32(0))
  655. dc->Draw(u32((s.vertex_buffer_cpu_used - s.vertex_buffer_offset)/shd.vertex_size), u32(s.vertex_buffer_offset/shd.vertex_size))
  656. s.vertex_buffer_offset = s.vertex_buffer_cpu_used
  657. log_messages()
  658. }
  659. make_default_projection :: proc(w, h: int) -> matrix[4,4]f32 {
  660. return linalg.matrix_ortho3d_f32(0, f32(w), f32(h), 0, 0.001, 2)
  661. }
  662. d3d11_present :: proc() {
  663. d3d11_draw_current_batch()
  664. ch(s.swapchain->Present(1, {}))
  665. s.vertex_buffer_offset = 0
  666. s.vertex_buffer_cpu_used = 0
  667. }
  668. Shader_Constant_Location :: struct {
  669. buffer_idx: u32,
  670. offset: u32,
  671. }
  672. _load_shader :: proc(shader: string, layout_formats: []Shader_Input_Format = {}) -> Shader_Handle {
  673. vs_blob: ^d3d11.IBlob
  674. vs_blob_errors: ^d3d11.IBlob
  675. ch(d3d_compiler.Compile(raw_data(shader), len(shader), nil, nil, nil, "vs_main", "vs_5_0", 0, 0, &vs_blob, &vs_blob_errors))
  676. if vs_blob_errors != nil {
  677. log.error("Failed compiling shader:")
  678. log.error(strings.string_from_ptr((^u8)(vs_blob_errors->GetBufferPointer()), int(vs_blob_errors->GetBufferSize())))
  679. }
  680. vertex_shader: ^d3d11.IVertexShader
  681. ch(s.device->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nil, &vertex_shader))
  682. ref: ^d3d11.IShaderReflection
  683. ch(d3d_compiler.Reflect(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), d3d11.ID3D11ShaderReflection_UUID, (^rawptr)(&ref)))
  684. constant_buffers: []Shader_Constant_Buffer
  685. constant_lookup: map[string]Shader_Constant_Location
  686. constant_builtin_locations: [Shader_Builtin_Constant]Maybe(Shader_Constant_Location)
  687. inputs: []Shader_Input
  688. {
  689. context.allocator = s.allocator
  690. d: d3d11.SHADER_DESC
  691. ch(ref->GetDesc(&d))
  692. inputs = make([]Shader_Input, d.InputParameters)
  693. for in_idx in 0..<d.InputParameters {
  694. in_desc: d3d11.SIGNATURE_PARAMETER_DESC
  695. if ch(ref->GetInputParameterDesc(in_idx, &in_desc)) < 0 {
  696. log.errorf("Invalid input: %v in shader %v", in_idx, shader)
  697. continue
  698. }
  699. type: Shader_Input_Type
  700. if in_desc.SemanticIndex > 0 {
  701. log.errorf("Matrix shader input types not yet implemented")
  702. continue
  703. }
  704. switch in_desc.ComponentType {
  705. case .UNKNOWN: log.errorf("Unknown component type")
  706. case .UINT32: log.errorf("Not implemented")
  707. case .SINT32: log.errorf("Not implemented")
  708. case .FLOAT32:
  709. switch in_desc.Mask {
  710. case 0: log.errorf("Invalid input mask"); continue
  711. case 1: type = .F32
  712. case 3: type = .Vec2
  713. case 7: type = .Vec3
  714. case 15: type = .Vec4
  715. }
  716. }
  717. inputs[in_idx] = {
  718. name = strings.clone_from_cstring(in_desc.SemanticName),
  719. register = int(in_idx),
  720. type = type,
  721. }
  722. }
  723. constant_buffers = make([]Shader_Constant_Buffer, d.ConstantBuffers)
  724. for cb_idx in 0..<d.ConstantBuffers {
  725. cb_info := ref->GetConstantBufferByIndex(cb_idx)
  726. if cb_info == nil {
  727. continue
  728. }
  729. cb_desc: d3d11.SHADER_BUFFER_DESC
  730. cb_info->GetDesc(&cb_desc)
  731. if cb_desc.Size == 0 {
  732. continue
  733. }
  734. b := &constant_buffers[cb_idx]
  735. b.cpu_data = make([]u8, cb_desc.Size, s.allocator)
  736. constant_buffer_desc := d3d11.BUFFER_DESC{
  737. ByteWidth = cb_desc.Size,
  738. Usage = .DYNAMIC,
  739. BindFlags = {.CONSTANT_BUFFER},
  740. CPUAccessFlags = {.WRITE},
  741. }
  742. ch(s.device->CreateBuffer(&constant_buffer_desc, nil, &b.gpu_data))
  743. for var_idx in 0..<cb_desc.Variables {
  744. var_info := cb_info->GetVariableByIndex(var_idx)
  745. if var_info == nil {
  746. continue
  747. }
  748. var_desc: d3d11.SHADER_VARIABLE_DESC
  749. var_info->GetDesc(&var_desc)
  750. if var_desc.Name != "" {
  751. loc := Shader_Constant_Location {
  752. buffer_idx = cb_idx,
  753. offset = var_desc.StartOffset,
  754. }
  755. constant_lookup[strings.clone_from_cstring(var_desc.Name)] = loc
  756. switch var_desc.Name {
  757. case "mvp":
  758. constant_builtin_locations[.MVP] = loc
  759. }
  760. }
  761. // TODO add the size or type somewhere so we set it correctly
  762. /*log.info(var_desc)
  763. type_info := var_info->GetType()
  764. type_info_desc: d3d11.SHADER_TYPE_DESC
  765. type_info->GetDesc(&type_info_desc)
  766. log.info(type_info_desc)*/
  767. }
  768. }
  769. }
  770. default_input_offsets: [Shader_Default_Inputs]int
  771. for &d in default_input_offsets {
  772. d = -1
  773. }
  774. input_offset: int
  775. if len(layout_formats) > 0 {
  776. if len(layout_formats) != len(inputs) {
  777. log.error("Passed number of layout formats isn't same as number of shader inputs")
  778. } else {
  779. for &i, idx in inputs {
  780. i.format = layout_formats[idx]
  781. if i.name == "POS" && i.type == .Vec2 {
  782. default_input_offsets[.Position] = input_offset
  783. } else if i.name == "UV" && i.type == .Vec2 {
  784. default_input_offsets[.UV] = input_offset
  785. } else if i.name == "COL" && i.type == .Vec4 {
  786. default_input_offsets[.Color] = input_offset
  787. }
  788. input_offset += shader_input_format_size(i.format)
  789. }
  790. }
  791. } else {
  792. for &i in inputs {
  793. if i.name == "POS" && i.type == .Vec2 {
  794. i.format = .RG32_Float
  795. default_input_offsets[.Position] = input_offset
  796. } else if i.name == "UV" && i.type == .Vec2 {
  797. i.format = .RG32_Float
  798. default_input_offsets[.UV] = input_offset
  799. } else if i.name == "COL" && i.type == .Vec4 {
  800. i.format = .RGBA8_Norm
  801. default_input_offsets[.Color] = input_offset
  802. } else {
  803. switch i.type {
  804. case .F32: i.format = .R32_Float
  805. case .Vec2: i.format = .RG32_Float
  806. case .Vec3: i.format = .RGBA32_Float
  807. case .Vec4: i.format = .RGBA32_Float
  808. }
  809. }
  810. input_offset += shader_input_format_size(i.format)
  811. }
  812. }
  813. input_layout_desc := make([]d3d11.INPUT_ELEMENT_DESC, len(inputs), context.temp_allocator)
  814. for idx in 0..<len(inputs) {
  815. input := inputs[idx]
  816. input_layout_desc[idx] = {
  817. SemanticName = temp_cstring(input.name),
  818. Format = dxgi_format_from_shader_input_format(input.format),
  819. AlignedByteOffset = idx == 0 ? 0 : d3d11.APPEND_ALIGNED_ELEMENT,
  820. InputSlotClass = .VERTEX_DATA,
  821. }
  822. }
  823. input_layout: ^d3d11.IInputLayout
  824. ch(s.device->CreateInputLayout(raw_data(input_layout_desc), u32(len(input_layout_desc)), vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &input_layout))
  825. ps_blob: ^d3d11.IBlob
  826. ps_blob_errors: ^d3d11.IBlob
  827. ch(d3d_compiler.Compile(raw_data(shader), len(shader), nil, nil, nil, "ps_main", "ps_5_0", 0, 0, &ps_blob, &ps_blob_errors))
  828. if ps_blob_errors != nil {
  829. log.error("Failed compiling shader:")
  830. log.error(strings.string_from_ptr((^u8)(ps_blob_errors->GetBufferPointer()), int(ps_blob_errors->GetBufferSize())))
  831. }
  832. pixel_shader: ^d3d11.IPixelShader
  833. ch(s.device->CreatePixelShader(ps_blob->GetBufferPointer(), ps_blob->GetBufferSize(), nil, &pixel_shader))
  834. shd := Shader {
  835. vertex_shader = vertex_shader,
  836. pixel_shader = pixel_shader,
  837. input_layout = input_layout,
  838. constant_buffers = constant_buffers,
  839. constant_lookup = constant_lookup,
  840. constant_builtin_locations = constant_builtin_locations,
  841. inputs = inputs,
  842. input_overrides = make([]Shader_Input_Value_Override, len(inputs)),
  843. default_input_offsets = default_input_offsets,
  844. vertex_size = input_offset,
  845. }
  846. h := hm.add(&s.shaders, shd)
  847. return h
  848. }
  849. dxgi_format_from_shader_input_format :: proc(f: Shader_Input_Format) -> dxgi.FORMAT {
  850. switch f {
  851. case .Unknown: return .UNKNOWN
  852. case .RGBA32_Float: return .R32G32B32A32_FLOAT
  853. case .RGBA8_Norm: return .R8G8B8A8_UNORM
  854. case .RGBA8_Norm_SRGB: return .R8G8B8A8_UNORM_SRGB
  855. case .RG32_Float: return .R32G32_FLOAT
  856. case .R32_Float: return .R32_FLOAT
  857. }
  858. log.error("Unknown format")
  859. return .UNKNOWN
  860. }
  861. shader_input_format_size :: proc(f: Shader_Input_Format) -> int {
  862. switch f {
  863. case .Unknown: return 0
  864. case .RGBA32_Float: return 32
  865. case .RGBA8_Norm: return 4
  866. case .RGBA8_Norm_SRGB: return 4
  867. case .RG32_Float: return 8
  868. case .R32_Float: return 4
  869. }
  870. return 0
  871. }
  872. _destroy_shader :: proc(shader: Shader_Handle) {
  873. if shd := hm.get(&s.shaders, shader); shd != nil {
  874. shd.input_layout->Release()
  875. shd.vertex_shader->Release()
  876. shd.pixel_shader->Release()
  877. for c in shd.constant_buffers {
  878. if c.gpu_data != nil {
  879. c.gpu_data->Release()
  880. }
  881. delete(c.cpu_data)
  882. }
  883. delete(shd.constant_buffers)
  884. for k,_ in shd.constant_lookup {
  885. delete(k)
  886. }
  887. delete(shd.constant_lookup)
  888. for i in shd.inputs {
  889. delete(i.name)
  890. }
  891. delete(shd.inputs)
  892. }
  893. hm.remove(&s.shaders, shader)
  894. }
  895. _get_shader_constant_location :: proc(shader: Shader_Handle, name: string) -> Shader_Constant_Location {
  896. shd := hm.get(&s.shaders, shader)
  897. if shd == nil {
  898. return {}
  899. }
  900. return shd.constant_lookup[name]
  901. }
  902. temp_cstring :: proc(str: string, loc := #caller_location) -> cstring {
  903. return strings.clone_to_cstring(str, context.temp_allocator, loc)
  904. }
  905. // CHeck win errors and print message log if there is any error
  906. ch :: proc(hr: win32.HRESULT, loc := #caller_location) -> win32.HRESULT {
  907. if hr >= 0 {
  908. return hr
  909. }
  910. log.errorf("d3d11 error: %0x", u32(hr), location = loc)
  911. log_messages(loc)
  912. return hr
  913. }
  914. log_messages :: proc(loc := #caller_location) {
  915. iq := s.info_queue
  916. if iq == nil {
  917. return
  918. }
  919. n := iq->GetNumStoredMessages()
  920. longest_msg: d3d11.SIZE_T
  921. for i in 0..=n {
  922. msglen: d3d11.SIZE_T
  923. iq->GetMessage(i, nil, &msglen)
  924. if msglen > longest_msg {
  925. longest_msg = msglen
  926. }
  927. }
  928. if longest_msg > 0 {
  929. msg_raw_ptr, _ := (mem.alloc(int(longest_msg), allocator = context.temp_allocator))
  930. for i in 0..=n {
  931. msglen: d3d11.SIZE_T
  932. iq->GetMessage(i, nil, &msglen)
  933. if msglen > 0 {
  934. msg := (^d3d11.MESSAGE)(msg_raw_ptr)
  935. iq->GetMessage(i, msg, &msglen)
  936. log.error(msg.pDescription, location = loc)
  937. }
  938. }
  939. }
  940. iq->ClearStoredMessages()
  941. }