Constant Buffer

マウス座標と ViewPort サイズを ConstantBuffer 経由で送り込んでカーソル位置に三角形を描画する。

../../assets/constant.hlsl
void vsMain() {}

struct DummyInput {};
struct GS_OUTPUT {
  float4 position : SV_POSITION;
  float4 color : COLOR0;
};

float4 xywh;

float pixel_to_screen_x(float x) { return (x / xywh.z) * 2 - 1; }
float pixel_to_screen_y(float y) { return (y / xywh.w) * 2 - 1; }

[maxvertexcount(3)] void gsMain(point DummyInput input[1]
                                : POSITION,
                                  inout TriangleStream<GS_OUTPUT> output) {
  GS_OUTPUT element;

  // rect
  const float size = 10;
  float l = pixel_to_screen_x(xywh.x - size);
  float r = pixel_to_screen_x(xywh.x + size);
  float b = -pixel_to_screen_y(xywh.y + size);
  float t = -pixel_to_screen_y(xywh.y - size);

  // d3d default. clock wise

  // 0
  element.position = float4(l, b, 0, 1);
  element.color = float4(1, 0, 0, 1);
  output.Append(element);
  // 1
  element.position = float4(l, t, 0, 1);
  element.color = float4(0, 1, 0, 1);
  output.Append(element);
  // 2
  element.position = float4(r, t, 0, 1);
  element.color = float4(0, 0, 1, 1);
  output.Append(element);

  output.RestartStrip();
}

float4 psMain(GS_OUTPUT V)
    : SV_Target {
  return V.color;
}
../../lib/gorilla/constant_buffer.cpp
#include "constant_buffer.h"
#include <assert.h>

namespace gorilla {

bool ConstantBuffer::create(const ComPtr<ID3D11Device> &device, UINT size) {
  desc.ByteWidth = size;
  desc.Usage = D3D11_USAGE_DEFAULT;
  desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  auto hr = device->CreateBuffer(&desc, nullptr, &buffer);
  if (FAILED(hr)) {
    return false;
  }
  return true;
}

void ConstantBuffer::update(const ComPtr<ID3D11DeviceContext> &context,
                            const void *p, size_t size) {
  assert(desc.ByteWidth == size);
  context->UpdateSubresource(buffer.Get(), 0, nullptr, p, 0, 0);
}

} // namespace gorilla

CPU側のメモリレイアウト

16バイトアライメント。 例えば、hlsl の float3x3 は,

struct Mat3 {
float _11, _12, _13, padding,
_21, _22, _23, padding,
_31, _32, _33, padding,
};

になることに注意する。 DirectX::FLOAT3X3 ではなく DirectX::FLOAT3X4 に格納する必要がある。