#include "graphics_device.h" #include #include GraphicsDevice* graphics_device_create(void) { return (GraphicsDevice*)calloc(1, sizeof(GraphicsDevice)); } void graphics_device_destroy(GraphicsDevice* d) { if (!d) return; if (d->depth_stencil) d->depth_stencil->lpVtbl->Release(d->depth_stencil); if (d->depth_texture) d->depth_texture->lpVtbl->Release(d->depth_texture); if (d->render_target) d->render_target->lpVtbl->Release(d->render_target); if (d->swap_chain) d->swap_chain->lpVtbl->Release(d->swap_chain); if (d->context) d->context->lpVtbl->Release(d->context); if (d->device) d->device->lpVtbl->Release(d->device); free(d); } static int create_depth_stencil(GraphicsDevice* d, uint32_t w, uint32_t h) { D3D11_TEXTURE2D_DESC desc = {0}; desc.Width = w; desc.Height = h; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; HRESULT hr = d->device->lpVtbl->CreateTexture2D(d->device, &desc, NULL, &d->depth_texture); if (FAILED(hr)) return 0; D3D11_DEPTH_STENCIL_VIEW_DESC dsv = {0}; dsv.Format = desc.Format; dsv.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; hr = d->device->lpVtbl->CreateDepthStencilView(d->device, (ID3D11Resource*)d->depth_texture, &dsv, &d->depth_stencil); return SUCCEEDED(hr); } int graphics_device_init(GraphicsDevice* d, void* hwnd, uint32_t w, uint32_t h, int vsync) { d->width = w; d->height = h; d->vsync = vsync; DXGI_SWAP_CHAIN_DESC scd = {0}; scd.BufferCount = 1; scd.BufferDesc.Width = w; scd.BufferDesc.Height = h; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferDesc.RefreshRate.Numerator = 60; scd.BufferDesc.RefreshRate.Denominator = 1; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.OutputWindow = (HWND)hwnd; scd.SampleDesc.Count = 1; scd.Windowed = TRUE; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; D3D_FEATURE_LEVEL levels[] = {D3D_FEATURE_LEVEL_11_0}; UINT flags = 0; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, 1, D3D11_SDK_VERSION, &scd, &d->swap_chain, &d->device, NULL, &d->context); if (FAILED(hr)) return 0; ID3D11Texture2D* back_buffer = NULL; d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer); d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target); if (back_buffer) back_buffer->lpVtbl->Release(back_buffer); create_depth_stencil(d, w, h); d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil); D3D11_VIEWPORT vp = {0}; vp.Width = (float)w; vp.Height = (float)h; vp.MaxDepth = 1.0f; d->context->lpVtbl->RSSetViewports(d->context, 1, &vp); // 设置默认深度状态 (避免 UILayer init 破坏) D3D11_DEPTH_STENCIL_DESC dsd = {0}; dsd.DepthEnable = TRUE; dsd.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; dsd.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; ID3D11DepthStencilState* default_dss = NULL; d->device->lpVtbl->CreateDepthStencilState(d->device, &dsd, &default_dss); if (default_dss) { d->context->lpVtbl->OMSetDepthStencilState(d->context, default_dss, 0); default_dss->lpVtbl->Release(default_dss); } return 1; } void graphics_device_resize(GraphicsDevice* d, uint32_t w, uint32_t h) { if (w == 0 || h == 0) return; d->context->lpVtbl->OMSetRenderTargets(d->context, 0, NULL, NULL); if (d->render_target) { d->render_target->lpVtbl->Release(d->render_target); d->render_target = NULL; } if (d->depth_stencil) { d->depth_stencil->lpVtbl->Release(d->depth_stencil); d->depth_stencil = NULL; } if (d->depth_texture) { d->depth_texture->lpVtbl->Release(d->depth_texture); d->depth_texture = NULL; } d->swap_chain->lpVtbl->ResizeBuffers(d->swap_chain, 0, w, h, DXGI_FORMAT_UNKNOWN, 0); ID3D11Texture2D* back_buffer = NULL; d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer); d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target); if (back_buffer) back_buffer->lpVtbl->Release(back_buffer); create_depth_stencil(d, w, h); d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil); D3D11_VIEWPORT vp = {0}; vp.Width = (float)w; vp.Height = (float)h; vp.MaxDepth = 1.0f; d->context->lpVtbl->RSSetViewports(d->context, 1, &vp); d->width = w; d->height = h; } void graphics_device_clear(GraphicsDevice* d, float r, float g, float b, float a) { float color[4] = {r, g, b, a}; d->context->lpVtbl->ClearRenderTargetView(d->context, d->render_target, color); d->context->lpVtbl->ClearDepthStencilView(d->context, d->depth_stencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } void graphics_device_present(GraphicsDevice* d) { d->swap_chain->lpVtbl->Present(d->swap_chain, d->vsync ? 1 : 0, 0); }