This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository Direct3D.wiki.
View the commit online.
commit d9e022298cd4318559e9d690bb157f7c90361030
Author: Vincent Torri <vincent.to...@gmail.com>
AuthorDate: Fri Aug 18 22:47:24 2023 -0700
Update 'Direct3D 11 for 2D: Display a pink triangle'
---
Direct3D-11-for-2D%3A-Display-a-pink-triangle.md | 1091 +++++++++++++++++++++-
1 file changed, 1090 insertions(+), 1 deletion(-)
diff --git a/Direct3D-11-for-2D%3A-Display-a-pink-triangle.md b/Direct3D-11-for-2D%3A-Display-a-pink-triangle.md
index 7b783fe..bd07111 100644
--- a/Direct3D-11-for-2D%3A-Display-a-pink-triangle.md
+++ b/Direct3D-11-for-2D%3A-Display-a-pink-triangle.md
@@ -1236,4 +1236,1093 @@ Note that the width and height are obviously needed for the computations. These
FLOAT ivps[4]; /* inverse viewport size */
```
-and the 2 first elements are the inverse of the width and height. The 2 other elements are unused and set to 0. Once this array is filled, we copy it to the GPU with the `Map()` function. Here are the shader and C files, with their diff:
\ No newline at end of file
+and the 2 first elements are the inverse of the width and height. The 2 other elements are unused and set to 0. Once this array is filled, we copy it to the GPU with the `Map()` function. Here are the shader and C files, with their diff:
+
+**shader_2.hlsl**
+
+```c
+cbuffer cv_viewport : register(b0)
+{
+ float2 viewport_inv_size;
+ float2 dummy; /* unused, to have a multiple of 16 bytes */
+}
+
+struct vs_input
+{
+ uint2 position : POSITION;
+};
+
+struct ps_input
+{
+ float4 position : SV_POSITION;
+};
+
+ps_input main_vs(vs_input input )
+{
+ ps_input output;
+ float2 p = input.position;
+ p *= viewport_inv_size;
+ p *= 2.0f;
+ p -= 1.0f;
+ p.y *= -1.0f;
+ output.position = float4(p, 0.0f, 1.0f);
+ return output;
+}
+
+float4 main_ps(ps_input input) : SV_TARGET
+{
+ return float4(1.0f, 0.0f, 1.0f, 1.0f);
+}
+```
+
+**shader_2.diff**
+
+```diff
+--- shader_1.hlsl 2023-08-16 08:32:39.100716400 +0200
++++ shader_2.hlsl 2023-08-19 07:43:25.508151800 +0200
+@@ -1,6 +1,12 @@
++cbuffer cv_viewport : register(b0)
++{
++ float2 viewport_inv_size;
++ float2 dummy; /* unused, to have a multiple of 16 bytes */
++}
++
+ struct vs_input
+ {
+- float2 position : POSITION;
++ uint2 position : POSITION;
+ };
+
+ struct ps_input
+@@ -8,25 +14,18 @@
+ float4 position : SV_POSITION;
+ };
+
+-/*
+- * vertex shater program
+- *
+- * @param input the 2 coordinates of a vertex, got from CPU
+- * @return the 4D position of the pixel corresponding to the vertex in GPU
+- */
+ ps_input main_vs(vs_input input )
+ {
+ ps_input output;
+- output.position = float4(input.position, 0.0f, 1.0f);
++ float2 p = input.position;
++ p *= viewport_inv_size;
++ p *= 2.0f;
++ p -= 1.0f;
++ p.y *= -1.0f;
++ output.position = float4(p, 0.0f, 1.0f);
+ return output;
+ }
+
+-/*
+- * pixel shater program
+- *
+- * @param input the 4D coordinates of a pixel
+- * @return the color of the pixel in RGBA colorspace, here pink
+- */
+ float4 main_ps(ps_input input) : SV_TARGET
+ {
+ return float4(1.0f, 0.0f, 1.0f, 1.0f);
+```
+
+**d3d_3.c**
+
+```c
+/*
+ * Tutorial part 3
+ *
+ * Display pink triangle
+ * Add HLSL code and compile it at runtime (sufficient for now)
+ * Computation of coordinates in GPU
+ *
+ * Compilation:
+ *
+ * gcc -g -O2 -Wall -Wextra -o d3d_3 d3d_3.c win.c -ld3d11 -ld3dcompiler -ldxgi -luuid -D_WIN32_WINNT=0x0A00
+ */
+
+#include <stdlib.h> /* calloc() free() malloc() */
+#include <stdio.h> /* printf() fflush() */
+
+#define _DEBUG
+
+/* C API for d3d11 */
+#define COBJMACROS
+
+#include <dxgi1_3.h> /* DXGI interface */
+#include <d3d11.h> /* D3D11 interface */
+#include <d3dcompiler.h> /* compilation of shader */
+
+#include "win.h"
+
+#ifdef _DEBUG
+# define FCT \
+do { printf(" * %s\n", __FUNCTION__); fflush(stdout); } while (0)
+#else
+# define FCT \
+do { } while (0)
+#endif
+
+struct D3d
+{
+ /* DXGI */
+ IDXGIFactory2 *dxgi_factory;
+ IDXGISwapChain1 *dxgi_swapchain;
+ /* D3D11 */
+ ID3D11Device *d3d_device;
+#ifdef _DEBUG
+ ID3D11Debug *d3d_debug;
+#endif
+ ID3D11DeviceContext *d3d_device_ctx;
+ ID3D11RenderTargetView *d3d_render_target_view;
+ ID3D11InputLayout *d3d_input_layout;
+ ID3D11VertexShader *d3d_vertex_shader;
+ ID3D11Buffer *d3d_const_buffer;
+ ID3D11RasterizerState *d3d_rasterizer_state;
+ ID3D11PixelShader *d3d_pixel_shader;
+ D3D11_VIEWPORT viewport;
+ unsigned int vsync : 1;
+};
+
+typedef struct
+{
+ UINT x;
+ UINT y;
+} Vertex;
+
+typedef struct
+{
+ float ivps[2]; /* inverse viewport size */
+ float dummy[2]; /* for 16 bytes padding */
+} Const_Buffer;
+
+typedef struct
+{
+ ID3D11Buffer *vertex_buffer;
+ ID3D11Buffer *index_buffer; /* not useful for a single triangle */
+ UINT stride;
+ UINT offset;
+ UINT index_count;
+} Object;
+
+static Object *objects[1];
+
+/************************** D3D11 **************************/
+
+static void d3d_refresh_rate_get(D3d *d3d, UINT *num, UINT *den)
+{
+ DXGI_MODE_DESC *display_mode_list = NULL; /* 28 bytes */
+ IDXGIAdapter *dxgi_adapter;
+ IDXGIOutput *dxgi_output;
+ UINT nbr_modes;
+ UINT i;
+ HRESULT res;
+
+ *num = 0U;
+ *den = 1U;
+
+ if (!d3d->vsync)
+ return;
+
+ /* adapter of primary desktop : pass 0U */
+ res = IDXGIFactory_EnumAdapters(d3d->dxgi_factory, 0U, &dxgi_adapter);
+ if (FAILED(res))
+ return;
+
+ /* output of primary desktop : pass 0U */
+ res = IDXGIAdapter_EnumOutputs(dxgi_adapter, 0U, &dxgi_output);
+ if (FAILED(res))
+ goto release_dxgi_adapter;
+
+ /* number of mode that fit the format */
+ res = IDXGIOutput_GetDisplayModeList(dxgi_output,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_ENUM_MODES_INTERLACED,
+ &nbr_modes, NULL);
+ if (FAILED(res))
+ goto release_dxgi_output;
+
+ printf("display mode list : %d\n", nbr_modes);
+ fflush(stdout);
+ display_mode_list = (DXGI_MODE_DESC *)malloc(nbr_modes * sizeof(DXGI_MODE_DESC));
+ if (!display_mode_list)
+ goto release_dxgi_output;
+
+ /* fill the mode list */
+ res = IDXGIOutput_GetDisplayModeList(dxgi_output,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_ENUM_MODES_INTERLACED,
+ &nbr_modes, display_mode_list);
+ if (FAILED(res))
+ goto free_mode_list;
+
+ for (i = 0; i < nbr_modes; i++)
+ {
+ if ((display_mode_list[i].Width == (UINT)GetSystemMetrics(SM_CXSCREEN)) &&
+ (display_mode_list[i].Height == (UINT)GetSystemMetrics(SM_CYSCREEN)))
+ {
+ *num = display_mode_list[i].RefreshRate.Numerator;
+ *den = display_mode_list[i].RefreshRate.Denominator;
+ break;
+ }
+ }
+
+#ifdef _DEBUG
+ {
+ DXGI_ADAPTER_DESC adapter_desc;
+
+ IDXGIAdapter_GetDesc(dxgi_adapter, &adapter_desc);
+ printf(" * video mem: %llu B, %llu MB\n",
+ adapter_desc.DedicatedVideoMemory,
+ adapter_desc.DedicatedVideoMemory / 1024 / 1024);
+ fflush(stdout);
+ wprintf(L" * description: %ls\n", adapter_desc.Description);
+ fflush(stdout);
+ }
+#endif
+
+ free_mode_list:
+ free(display_mode_list);
+ release_dxgi_output:
+ IDXGIOutput_Release(dxgi_output);
+ release_dxgi_adapter:
+ IDXGIFactory_Release(dxgi_adapter);
+}
+
+D3d *d3d_init(Window *win, int vsync)
+{
+ D3D11_INPUT_ELEMENT_DESC desc_ie[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_UINT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+ };
+ DXGI_SWAP_CHAIN_DESC1 desc_sw;
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC desc_fs;
+ D3D11_BUFFER_DESC desc_buf;
+ D3D11_RASTERIZER_DESC desc_rs;
+ D3d *d3d;
+ RECT r;
+ HRESULT res;
+ UINT flags;
+ UINT num;
+ UINT den;
+ D3D_FEATURE_LEVEL feature_level[4];
+ ID3DBlob *vs_blob; /* vertex shader blob ptr */
+ ID3DBlob *ps_blob; /* pixel shader blob ptr */
+ ID3DBlob *err_blob; /* error blob ptr */
+
+ d3d = (D3d *)calloc(1, sizeof(D3d));
+ if (!d3d)
+ return NULL;
+
+ d3d->vsync = vsync;
+ win->d3d = d3d;
+
+ /* create the DXGI factory */
+ flags = 0;
+#ifdef _DEBUG
+ flags = DXGI_CREATE_FACTORY_DEBUG;
+#endif
+ res = CreateDXGIFactory2(flags, &IID_IDXGIFactory2, (void **)&d3d->dxgi_factory);
+ if (FAILED(res))
+ goto free_d3d;
+
+ /* software engine functions are called from the main loop */
+ flags = D3D11_CREATE_DEVICE_SINGLETHREADED |
+ D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#ifdef _DEBUG
+ flags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ feature_level[0] = D3D_FEATURE_LEVEL_11_1;
+ feature_level[1] = D3D_FEATURE_LEVEL_11_0;
+ feature_level[2] = D3D_FEATURE_LEVEL_10_1;
+ feature_level[3] = D3D_FEATURE_LEVEL_10_0;
+
+ /* create device and device context with hardware support */
+ res = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ flags,
+ feature_level,
+ 3U,
+ D3D11_SDK_VERSION,
+ &d3d->d3d_device,
+ NULL,
+ &d3d->d3d_device_ctx);
+ if (FAILED(res))
+ goto release_dxgi_factory2;
+
+#ifdef _DEBUG
+ res = ID3D11Debug_QueryInterface(d3d->d3d_device, &IID_ID3D11Debug,
+ (void **)&d3d->d3d_debug);
+ if (FAILED(res))
+ goto release_d3d_device;
+#endif
+
+ if (!GetClientRect(win->win, &r))
+ goto release_d3d_device;
+
+ /*
+ * create the swap chain. It needs some settings...
+ * the size of the internal buffers
+ * the image format
+ * the number of back buffers (>= 2 for flip model, see SwapEffect field)
+ * vsync enabled: need refresh rate
+ */
+
+ d3d_refresh_rate_get(d3d, &num, &den);
+
+ desc_sw.Width = r.right - r.left;
+ desc_sw.Height = r.bottom - r.top;
+ desc_sw.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc_sw.Stereo = FALSE;
+ desc_sw.SampleDesc.Count = 1U;
+ desc_sw.SampleDesc.Quality = 0U;
+ desc_sw.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc_sw.BufferCount = 2U;
+ desc_sw.Scaling = DXGI_SCALING_NONE;
+ desc_sw.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ desc_sw.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+ desc_sw.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ desc_fs.RefreshRate.Numerator = num;
+ desc_fs.RefreshRate.Denominator = den;
+ desc_fs.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ desc_fs.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ desc_fs.Windowed = TRUE;
+
+ res = IDXGIFactory2_CreateSwapChainForHwnd(d3d->dxgi_factory,
+ (IUnknown *)d3d->d3d_device,
+ win->win,
+ &desc_sw,
+ &desc_fs,
+ NULL,
+ &d3d->dxgi_swapchain);
+ if (FAILED(res))
+ goto release_d3d_device;
+
+ /* rasterizer */
+ desc_rs.FillMode = D3D11_FILL_SOLID;
+ desc_rs.CullMode = D3D11_CULL_NONE;
+ desc_rs.FrontCounterClockwise = FALSE;
+ desc_rs.DepthBias = 0;
+ desc_rs.DepthBiasClamp = 0.0f;
+ desc_rs.SlopeScaledDepthBias = 0.0f;
+ desc_rs.DepthClipEnable = TRUE;
+ desc_rs.ScissorEnable = FALSE;
+ desc_rs.MultisampleEnable = FALSE;
+ desc_rs.AntialiasedLineEnable = FALSE;
+
+ res = ID3D11Device_CreateRasterizerState(d3d->d3d_device,
+ &desc_rs,
+ &d3d->d3d_rasterizer_state);
+ if (FAILED(res))
+ goto release_dxgi_swapchain;
+
+ /* Vertex shader */
+ flags = D3DCOMPILE_ENABLE_STRICTNESS;
+#ifdef _DEBUG
+ flags |= D3DCOMPILE_DEBUG;
+#endif
+ vs_blob = NULL;
+ res = D3DCompileFromFile(L"shader_2.hlsl",
+ NULL,
+ D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main_vs",
+ "vs_5_0",
+ flags,
+ 0U,
+ &vs_blob,
+ &err_blob );
+
+ if (FAILED(res))
+ {
+ printf(" * vs error : %s\n", (char *)ID3D10Blob_GetBufferPointer(err_blob));
+ goto release_d3D_rasterizer;
+ }
+
+ res = ID3D11Device_CreateVertexShader(d3d->d3d_device,
+ ID3D10Blob_GetBufferPointer(vs_blob),
+ ID3D10Blob_GetBufferSize(vs_blob),
+ NULL,
+ &d3d->d3d_vertex_shader);
+
+ if (FAILED(res))
+ {
+ printf(" * CreateVertexShader() failed\n");
+ ID3D10Blob_Release(vs_blob);
+ goto release_d3D_rasterizer;
+ }
+
+ /* create the input layout */
+ res = ID3D11Device_CreateInputLayout(d3d->d3d_device,
+ desc_ie,
+ sizeof(desc_ie) / sizeof(D3D11_INPUT_ELEMENT_DESC),
+ ID3D10Blob_GetBufferPointer(vs_blob),
+ ID3D10Blob_GetBufferSize(vs_blob),
+ &d3d->d3d_input_layout);
+ ID3D10Blob_Release(vs_blob);
+ if (FAILED(res))
+ {
+ printf(" * CreateInputLayout() failed\n");
+ goto release_vertex_shader;
+ }
+
+ /* Pixel shader */
+ ps_blob = NULL;
+ res = D3DCompileFromFile(L"shader_2.hlsl",
+ NULL,
+ D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main_ps",
+ "ps_5_0",
+ flags,
+ 0U,
+ &ps_blob,
+ &err_blob );
+
+ if (FAILED(res))
+ {
+ printf(" * ps blob error : %s\n", (char *)ID3D10Blob_GetBufferPointer(err_blob));
+ goto release_input_layout;
+ }
+
+ res = ID3D11Device_CreatePixelShader(d3d->d3d_device,
+ ID3D10Blob_GetBufferPointer(ps_blob),
+ ID3D10Blob_GetBufferSize(ps_blob),
+ NULL,
+ &d3d->d3d_pixel_shader);
+ ID3D10Blob_Release(ps_blob);
+ if (FAILED(res))
+ {
+ printf(" * CreatePixelShader() failed\n");
+ goto release_input_layout;
+ }
+
+ desc_buf.ByteWidth = sizeof(Const_Buffer);
+ desc_buf.Usage = D3D11_USAGE_DYNAMIC; /* because buffer is updated when the window has resized */
+ desc_buf.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc_buf.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc_buf.MiscFlags = 0;
+ desc_buf.StructureByteStride = 0;
+
+ res = ID3D11Device_CreateBuffer(d3d->d3d_device,
+ &desc_buf,
+ NULL,
+ &d3d->d3d_const_buffer);
+ if (FAILED(res))
+ {
+ printf(" * CreateBuffer() failed 0x%lx\n", res);
+ goto release_pixel_shader;
+ }
+
+ return d3d;
+
+ release_pixel_shader:
+ ID3D11PixelShader_Release(d3d->d3d_pixel_shader);
+ release_input_layout:
+ ID3D11InputLayout_Release(d3d->d3d_input_layout);
+ release_vertex_shader:
+ ID3D11VertexShader_Release(d3d->d3d_vertex_shader);
+ release_d3D_rasterizer:
+ ID3D11RasterizerState_Release(d3d->d3d_rasterizer_state);
+ release_dxgi_swapchain:
+ IDXGISwapChain1_SetFullscreenState(d3d->dxgi_swapchain, FALSE, NULL);
+ IDXGISwapChain1_Release(d3d->dxgi_swapchain);
+ release_d3d_device:
+#ifdef _DEBUG
+ if (d3d->d3d_debug)
+ ID3D11Debug_Release(d3d->d3d_debug);
+#endif
+ ID3D11DeviceContext_Release(d3d->d3d_device_ctx);
+ ID3D11Device_Release(d3d->d3d_device);
+ release_dxgi_factory2:
+ IDXGIFactory2_Release(d3d->dxgi_factory);
+ free_d3d:
+ free(d3d);
+
+ return NULL;
+}
+
+void d3d_shutdown(D3d *d3d)
+{
+#ifdef _DEBUG
+ ID3D11Debug *d3d_debug;
+#endif
+
+ if (!d3d)
+ return;
+
+#ifdef _DEBUG
+ d3d_debug = d3d->d3d_debug;
+#endif
+
+ ID3D11Buffer_Release(d3d->d3d_const_buffer);
+ ID3D11PixelShader_Release(d3d->d3d_pixel_shader);
+ ID3D11InputLayout_Release(d3d->d3d_input_layout);
+ ID3D11VertexShader_Release(d3d->d3d_vertex_shader);
+ ID3D11RasterizerState_Release(d3d->d3d_rasterizer_state);
+ ID3D11RenderTargetView_Release(d3d->d3d_render_target_view);
+ IDXGISwapChain1_SetFullscreenState(d3d->dxgi_swapchain, FALSE, NULL);
+ IDXGISwapChain1_Release(d3d->dxgi_swapchain);
+ ID3D11DeviceContext_Release(d3d->d3d_device_ctx);
+ ID3D11Device_Release(d3d->d3d_device);
+ IDXGIFactory2_Release(d3d->dxgi_factory);
+ free(d3d);
+
+#ifdef _DEBUG
+ ID3D11Debug_ReportLiveDeviceObjects(d3d_debug, D3D11_RLDO_DETAIL);
+ ID3D11Debug_Release(d3d_debug);
+#endif
+}
+
+void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
+{
+ D3D11_RENDER_TARGET_VIEW_DESC desc_rtv;
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ ID3D11Texture2D *back_buffer;
+ HRESULT res;
+
+ FCT;
+
+ res = ID3D11DeviceContext_Map(d3d->d3d_device_ctx,
+ (ID3D11Resource *)d3d->d3d_const_buffer,
+ 0U, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
+
+ if (FAILED(res))
+ {
+ printf("Map() failed\n");
+ fflush(stdout);
+ return;
+ }
+
+ ((Const_Buffer *)mapped.pData)->ivps[0] = 1.0f / (float)width;
+ ((Const_Buffer *)mapped.pData)->ivps[1] = 1.0f / (float)height;
+
+ ID3D11DeviceContext_Unmap(d3d->d3d_device_ctx,
+ (ID3D11Resource *)d3d->d3d_const_buffer,
+ 0U);
+
+ /* unset the render target view in the output merger */
+ ID3D11DeviceContext_OMSetRenderTargets(d3d->d3d_device_ctx,
+ 0U, NULL, NULL);
+
+ /* release the render target view */
+ if (d3d->d3d_render_target_view)
+ ID3D11RenderTargetView_Release(d3d->d3d_render_target_view);
+
+ /* resize the internal nuffers of the swapt chain to the new size */
+ res = IDXGISwapChain1_ResizeBuffers(d3d->dxgi_swapchain,
+ 0U, /* preserve buffer count */
+ width, height,
+ DXGI_FORMAT_UNKNOWN, /* preserve format */
+ 0U);
+ if ((res == DXGI_ERROR_DEVICE_REMOVED) ||
+ (res == DXGI_ERROR_DEVICE_RESET) ||
+ (res == DXGI_ERROR_DRIVER_INTERNAL_ERROR))
+ {
+ return;
+ }
+
+ if (FAILED(res))
+ {
+ printf("ResizeBuffers() failed\n");
+ fflush(stdout);
+ return;
+ }
+
+ /* get the internal buffer of the swap chain */
+ res = IDXGISwapChain1_GetBuffer(d3d->dxgi_swapchain, 0,
+ &IID_ID3D11Texture2D,
+ (void **)&back_buffer);
+ if (FAILED(res))
+ {
+ printf("swapchain GetBuffer() failed\n");
+ fflush(stdout);
+ return;
+ }
+
+ ZeroMemory(&desc_rtv, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
+ desc_rtv.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc_rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+
+ /* create the new render target view from this internal buffer */
+ res = ID3D11Device_CreateRenderTargetView(d3d->d3d_device,
+ (ID3D11Resource *)back_buffer,
+ &desc_rtv,
+ &d3d->d3d_render_target_view);
+
+ ID3D11Texture2D_Release(back_buffer);
+
+ /* update the pipeline with the new render target view */
+ ID3D11DeviceContext_OMSetRenderTargets(d3d->d3d_device_ctx,
+ 1U, &d3d->d3d_render_target_view,
+ NULL);
+
+ /* set viewport, depends on size of the window */
+ d3d->viewport.TopLeftX = 0.0f;
+ d3d->viewport.TopLeftY = 0.0f;
+ d3d->viewport.Width = (float)width;
+ d3d->viewport.Height = (float)height;
+ d3d->viewport.MinDepth = 0.0f;
+ d3d->viewport.MaxDepth = 1.0f;
+
+ /* update the pipeline with the new viewport */
+ ID3D11DeviceContext_RSSetViewports(d3d->d3d_device_ctx,
+ 1U, &d3d->viewport);
+}
+
+/*** triangle ***/
+
+Object *triangle_new(D3d *d3d,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3)
+{
+ Vertex vertices[3];
+ unsigned int indices[3];
+ D3D11_BUFFER_DESC desc;
+ D3D11_SUBRESOURCE_DATA sr_data;
+ Object *o;
+ HRESULT res;
+
+ o = (Object *)malloc(sizeof(Object));
+ if (!o)
+ return NULL;
+
+ vertices[0].x = x1;
+ vertices[0].y = y1;
+ vertices[1].x = x2;
+ vertices[1].y = y2;
+ vertices[2].x = x3;
+ vertices[2].y = y3;
+
+ indices[0] = 0;
+ indices[1] = 1;
+ indices[2] = 2;
+
+ o->stride = sizeof(Vertex);
+ o->offset = 0U;
+ o->index_count = 3U;
+
+ desc.ByteWidth = sizeof(vertices);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0U;
+ desc.StructureByteStride = 0U;
+
+ sr_data.pSysMem = vertices;
+ sr_data.SysMemPitch = 0U;
+ sr_data.SysMemSlicePitch = 0U;
+
+ res =ID3D11Device_CreateBuffer(d3d->d3d_device,
+ &desc,
+ &sr_data,
+ &o->vertex_buffer);
+ if (FAILED(res))
+ {
+ free(o);
+ return NULL;
+ }
+
+ desc.ByteWidth = sizeof(indices);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0U;
+ desc.StructureByteStride = 0U;
+
+ sr_data.pSysMem = indices;
+ sr_data.SysMemPitch = 0U;
+ sr_data.SysMemSlicePitch = 0U;
+
+ res =ID3D11Device_CreateBuffer(d3d->d3d_device,
+ &desc,
+ &sr_data,
+ &o->index_buffer);
+ if (FAILED(res))
+ {
+ ID3D11Buffer_Release(o->vertex_buffer);
+ free(o);
+ return NULL;
+ }
+
+ return o;
+}
+
+void object_free(void *o)
+{
+ if (!o)
+ return ;
+
+ ID3D11Buffer_Release(((Object *)o)->index_buffer);
+ ID3D11Buffer_Release(((Object *)o)->vertex_buffer);
+ free(o);
+}
+
+void d3d_scene_begin(D3d *d3d)
+{
+ Object *o;
+
+ o = triangle_new(d3d,
+ 320, 120,
+ 480, 360,
+ 160, 360);
+ objects[0] = o;
+}
+
+void d3d_scene_end(void)
+{
+ size_t i;
+
+ for (i = 0; i < sizeof(objects) / sizeof(Object *); i++)
+ object_free(objects[i]);
+}
+
+void d3d_render(D3d *d3d)
+{
+ DXGI_PRESENT_PARAMETERS pp;
+ const FLOAT color[4] = { 0.10f, 0.18f, 0.24f, 1.0f };
+ HRESULT res;
+
+ FCT;
+
+ /* clear render target */
+ ID3D11DeviceContext_ClearRenderTargetView(d3d->d3d_device_ctx,
+ d3d->d3d_render_target_view,
+ color);
+ /* Input Assembler (IA) stage */
+ ID3D11DeviceContext_IASetPrimitiveTopology(d3d->d3d_device_ctx,
+ D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ ID3D11DeviceContext_IASetInputLayout(d3d->d3d_device_ctx,
+ d3d->d3d_input_layout);
+
+ /* vertex shader stage */
+ ID3D11DeviceContext_VSSetShader(d3d->d3d_device_ctx,
+ d3d->d3d_vertex_shader,
+ NULL,
+ 0);
+ ID3D11DeviceContext_VSSetConstantBuffers(d3d->d3d_device_ctx,
+ 0,
+ 1,
+ &d3d->d3d_const_buffer);
+
+ /*
+ * Rasterizer Stage
+ *
+ * RSSetViewports() called in the resize() callback
+ */
+ ID3D11DeviceContext_RSSetState(d3d->d3d_device_ctx,
+ d3d->d3d_rasterizer_state);
+
+ /* pixel shader stage */
+ ID3D11DeviceContext_PSSetShader(d3d->d3d_device_ctx,
+ d3d->d3d_pixel_shader,
+ NULL,
+ 0);
+
+ /*
+ * Output Merger stage
+ *
+ * OMSetRenderTargets() called in the resize() callback
+ */
+
+ /* Input Assembler (IA) stage */
+ ID3D11DeviceContext_IASetVertexBuffers(d3d->d3d_device_ctx,
+ 0,
+ 1,
+ &objects[0]->vertex_buffer,
+ &objects[0]->stride,
+ &objects[0]->offset);
+ ID3D11DeviceContext_IASetIndexBuffer(d3d->d3d_device_ctx,
+ objects[0]->index_buffer,
+ DXGI_FORMAT_R32_UINT,
+ 0);
+
+ /* draw */
+ ID3D11DeviceContext_DrawIndexed(d3d->d3d_device_ctx,
+ objects[0]->index_count,
+ 0, 0);
+
+ /*
+ * present frame, that is, flip the back buffer and the front buffer
+ * if no vsync, we present immediatly
+ */
+ pp.DirtyRectsCount = 0;
+ pp.pDirtyRects = NULL;
+ pp.pScrollRect = NULL;
+ pp.pScrollOffset = NULL;
+ res = IDXGISwapChain1_Present1(d3d->dxgi_swapchain,
+ d3d->vsync ? 1 : 0, 0, &pp);
+ if (res == DXGI_ERROR_DEVICE_RESET || res == DXGI_ERROR_DEVICE_REMOVED)
+ {
+ printf("device removed or lost, need to recreate everything\n");
+ fflush(stdout);
+ }
+ else if (res == DXGI_STATUS_OCCLUDED)
+ {
+ printf("window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage\n");
+ fflush(stdout);
+ }
+}
+```
+
+**d3d_3.diff*
+
+```diff
+--- d3d_2.c 2023-08-17 13:29:23.597473100 +0200
++++ d3d_3.c 2023-08-17 13:22:40.211436900 +0200
+@@ -1,13 +1,13 @@
+ /*
+- * Tutorial part 2
++ * Tutorial part 3
+ *
+ * Display pink triangle
+ * Add HLSL code and compile it at runtime (sufficient for now)
+- * Computation of coordinates in CPU
++ * Computation of coordinates in GPU
+ *
+ * Compilation:
+ *
+- * gcc -g -O2 -Wall -Wextra -o d3d_2 d3d_2.c win.c -ld3d11 -ld3dcompiler -ldxgi -luuid -D_WIN32_WINNT=0x0A00
++ * gcc -g -O2 -Wall -Wextra -o d3d_3 d3d_3.c win.c -ld3d11 -ld3dcompiler -ldxgi -luuid -D_WIN32_WINNT=0x0A00
+ */
+
+ #include <stdlib.h> /* calloc() free() malloc() */
+@@ -32,9 +32,6 @@
+ do { } while (0)
+ #endif
+
+-#define XF(w,x) ((float)(2 * (x) - (w)) / (float)(w))
+-#define YF(h,y) ((float)((h) - 2 * (y)) / (float)(h))
+-
+ struct D3d
+ {
+ /* DXGI */
+@@ -49,6 +46,7 @@
+ ID3D11RenderTargetView *d3d_render_target_view;
+ ID3D11InputLayout *d3d_input_layout;
+ ID3D11VertexShader *d3d_vertex_shader;
++ ID3D11Buffer *d3d_const_buffer;
+ ID3D11RasterizerState *d3d_rasterizer_state;
+ ID3D11PixelShader *d3d_pixel_shader;
+ D3D11_VIEWPORT viewport;
+@@ -57,12 +55,18 @@
+
+ typedef struct
+ {
+- FLOAT x;
+- FLOAT y;
++ UINT x;
++ UINT y;
+ } Vertex;
+
+ typedef struct
+ {
++ float ivps[2]; /* inverse viewport size */
++ float dummy[2]; /* for 16 bytes padding */
++} Const_Buffer;
++
++typedef struct
++{
+ ID3D11Buffer *vertex_buffer;
+ ID3D11Buffer *index_buffer; /* not useful for a single triangle */
+ UINT stride;
+@@ -158,10 +162,11 @@
+ {
+ D3D11_INPUT_ELEMENT_DESC desc_ie[] =
+ {
+- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
++ { "POSITION", 0, DXGI_FORMAT_R32G32_UINT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
+ };
+ DXGI_SWAP_CHAIN_DESC1 desc_sw;
+ DXGI_SWAP_CHAIN_FULLSCREEN_DESC desc_fs;
++ D3D11_BUFFER_DESC desc_buf;
+ D3D11_RASTERIZER_DESC desc_rs;
+ D3d *d3d;
+ RECT r;
+@@ -289,7 +294,7 @@
+ flags |= D3DCOMPILE_DEBUG;
+ #endif
+ vs_blob = NULL;
+- res = D3DCompileFromFile(L"shader_1.hlsl",
++ res = D3DCompileFromFile(L"shader_2.hlsl",
+ NULL,
+ D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main_vs",
+@@ -313,7 +318,7 @@
+
+ if (FAILED(res))
+ {
+- printf(" * vs error : %s\n", (char *)ID3D10Blob_GetBufferPointer(err_blob));
++ printf(" * CreateVertexShader() failed\n");
+ ID3D10Blob_Release(vs_blob);
+ goto release_d3D_rasterizer;
+ }
+@@ -334,7 +339,7 @@
+
+ /* Pixel shader */
+ ps_blob = NULL;
+- res = D3DCompileFromFile(L"shader_1.hlsl",
++ res = D3DCompileFromFile(L"shader_2.hlsl",
+ NULL,
+ D3D_COMPILE_STANDARD_FILE_INCLUDE,
+ "main_ps",
+@@ -362,8 +367,27 @@
+ goto release_input_layout;
+ }
+
++ desc_buf.ByteWidth = sizeof(Const_Buffer);
++ desc_buf.Usage = D3D11_USAGE_DYNAMIC; /* because buffer is updated when the window has resized */
++ desc_buf.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
++ desc_buf.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
++ desc_buf.MiscFlags = 0;
++ desc_buf.StructureByteStride = 0;
++
++ res = ID3D11Device_CreateBuffer(d3d->d3d_device,
++ &desc_buf,
++ NULL,
++ &d3d->d3d_const_buffer);
++ if (FAILED(res))
++ {
++ printf(" * CreateBuffer() failed 0x%lx\n", res);
++ goto release_pixel_shader;
++ }
++
+ return d3d;
+
++ release_pixel_shader:
++ ID3D11PixelShader_Release(d3d->d3d_pixel_shader);
+ release_input_layout:
+ ID3D11InputLayout_Release(d3d->d3d_input_layout);
+ release_vertex_shader:
+@@ -401,6 +425,7 @@
+ d3d_debug = d3d->d3d_debug;
+ #endif
+
++ ID3D11Buffer_Release(d3d->d3d_const_buffer);
+ ID3D11PixelShader_Release(d3d->d3d_pixel_shader);
+ ID3D11InputLayout_Release(d3d->d3d_input_layout);
+ ID3D11VertexShader_Release(d3d->d3d_vertex_shader);
+@@ -422,11 +447,30 @@
+ void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC desc_rtv;
++ D3D11_MAPPED_SUBRESOURCE mapped;
+ ID3D11Texture2D *back_buffer;
+ HRESULT res;
+
+ FCT;
+
++ res = ID3D11DeviceContext_Map(d3d->d3d_device_ctx,
++ (ID3D11Resource *)d3d->d3d_const_buffer,
++ 0U, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
++
++ if (FAILED(res))
++ {
++ printf("Map() failed\n");
++ fflush(stdout);
++ return;
++ }
++
++ ((Const_Buffer *)mapped.pData)->ivps[0] = 1.0f / (float)width;
++ ((Const_Buffer *)mapped.pData)->ivps[1] = 1.0f / (float)height;
++
++ ID3D11DeviceContext_Unmap(d3d->d3d_device_ctx,
++ (ID3D11Resource *)d3d->d3d_const_buffer,
++ 0U);
++
+ /* unset the render target view in the output merger */
+ ID3D11DeviceContext_OMSetRenderTargets(d3d->d3d_device_ctx,
+ 0U, NULL, NULL);
+@@ -499,7 +543,6 @@
+ /*** triangle ***/
+
+ Object *triangle_new(D3d *d3d,
+- int w, int h,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3)
+@@ -515,12 +558,12 @@
+ if (!o)
+ return NULL;
+
+- vertices[0].x = XF(w, x1);
+- vertices[0].y = YF(h, y1);
+- vertices[1].x = XF(w, x2);
+- vertices[1].y = YF(h, y2);
+- vertices[2].x = XF(w, x3);
+- vertices[2].y = YF(h, y3);
++ vertices[0].x = x1;
++ vertices[0].y = y1;
++ vertices[1].x = x2;
++ vertices[1].y = y2;
++ vertices[2].x = x3;
++ vertices[2].y = y3;
+
+ indices[0] = 0;
+ indices[1] = 1;
+@@ -588,24 +631,9 @@
+
+ void d3d_scene_begin(D3d *d3d)
+ {
+- DXGI_SWAP_CHAIN_DESC1 desc;
+ Object *o;
+- HRESULT res;
+- int w;
+- int h;
+-
+- res = IDXGISwapChain1_GetDesc1(d3d->dxgi_swapchain, &desc);
+- if (FAILED(res))
+- return;
+-
+- w = desc.Width;
+- h = desc.Height;
+-
+- printf(" * swapchain size : %d %d\n", w, h);
+- fflush(stdout);
+
+ o = triangle_new(d3d,
+- w, h,
+ 320, 120,
+ 480, 360,
+ 160, 360);
+@@ -623,24 +651,11 @@
+ void d3d_render(D3d *d3d)
+ {
+ DXGI_PRESENT_PARAMETERS pp;
+- DXGI_SWAP_CHAIN_DESC1 desc;
+ const FLOAT color[4] = { 0.10f, 0.18f, 0.24f, 1.0f };
+ HRESULT res;
+- int w;
+- int h;
+
+ FCT;
+
+- res = IDXGISwapChain1_GetDesc1(d3d->dxgi_swapchain, &desc);
+- if (FAILED(res))
+- return;
+-
+- w = desc.Width;
+- h = desc.Height;
+-
+- printf(" * swapchain size : %d %d\n", w, h);
+- fflush(stdout);
+-
+ /* clear render target */
+ ID3D11DeviceContext_ClearRenderTargetView(d3d->d3d_device_ctx,
+ d3d->d3d_render_target_view,
+@@ -656,6 +671,10 @@
+ d3d->d3d_vertex_shader,
+ NULL,
+ 0);
++ ID3D11DeviceContext_VSSetConstantBuffers(d3d->d3d_device_ctx,
++ 0,
++ 1,
++ &d3d->d3d_const_buffer);
+
+ /*
+ * Rasterizer Stage
+```
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.