Files
WickedEngine/WickedEngine/wiGraphics.h
T

1220 lines
27 KiB
C++

#pragma once
#include "CommonInclude.h"
#include "wiVector.h"
#include <cassert>
#include <memory>
#include <string>
#include <limits>
namespace wi::graphics
{
struct Shader;
struct GPUResource;
struct GPUBuffer;
struct Texture;
enum class ValidationMode
{
Disabled, // No validation is enabled
Enabled, // CPU command validation
GPU // CPU and GPU-based validation
};
enum class ShaderStage
{
MS, // Mesh Shader
AS, // Amplification Shader
VS, // Vertex Shader
HS, // Hull Shader
DS, // Domain Shader
GS, // Geometry Shader
PS, // Pixel Shader
CS, // Compute Shader
LIB, // Shader Library
Count,
};
enum class ShaderFormat
{
NONE, // Not used
HLSL5, // DXBC
HLSL6, // DXIL
SPIRV, // SPIR-V
};
enum class ShaderModel
{
SM_5_0,
SM_6_0,
SM_6_1,
SM_6_2,
SM_6_3,
SM_6_4,
SM_6_5,
SM_6_6,
SM_6_7,
};
enum class PrimitiveTopology
{
UNDEFINED,
TRIANGLELIST,
TRIANGLESTRIP,
POINTLIST,
LINELIST,
LINESTRIP,
PATCHLIST,
};
enum class ComparisonFunc
{
NEVER,
LESS,
EQUAL,
LESS_EQUAL,
GREATER,
NOT_EQUAL,
GREATER_EQUAL,
ALWAYS,
};
enum class DepthWriteMask
{
ZERO, // Disables depth write
ALL, // Enables depth write
};
enum class StencilOp
{
KEEP,
ZERO,
REPLACE,
INCR_SAT,
DECR_SAT,
INVERT,
INCR,
DECR,
};
enum class Blend
{
ZERO,
ONE,
SRC_COLOR,
INV_SRC_COLOR,
SRC_ALPHA,
INV_SRC_ALPHA,
DEST_ALPHA,
INV_DEST_ALPHA,
DEST_COLOR,
INV_DEST_COLOR,
SRC_ALPHA_SAT,
BLEND_FACTOR,
INV_BLEND_FACTOR,
SRC1_COLOR,
INV_SRC1_COLOR,
SRC1_ALPHA,
INV_SRC1_ALPHA,
};
enum class BlendOp
{
ADD,
SUBTRACT,
REV_SUBTRACT,
MIN,
MAX,
};
enum class FillMode
{
WIREFRAME,
SOLID,
};
enum class CullMode
{
NONE,
FRONT,
BACK,
};
enum class InputClassification
{
PER_VERTEX_DATA,
PER_INSTANCE_DATA,
};
enum class Usage
{
DEFAULT, // CPU no access, GPU read/write
UPLOAD, // CPU write, GPU read
READBACK, // CPU read, GPU write
};
enum class TextureAddressMode
{
WRAP,
MIRROR,
CLAMP,
BORDER,
MIRROR_ONCE,
};
enum class Filter
{
MIN_MAG_MIP_POINT,
MIN_MAG_POINT_MIP_LINEAR,
MIN_POINT_MAG_LINEAR_MIP_POINT,
MIN_POINT_MAG_MIP_LINEAR,
MIN_LINEAR_MAG_MIP_POINT,
MIN_LINEAR_MAG_POINT_MIP_LINEAR,
MIN_MAG_LINEAR_MIP_POINT,
MIN_MAG_MIP_LINEAR,
ANISOTROPIC,
COMPARISON_MIN_MAG_MIP_POINT,
COMPARISON_MIN_MAG_POINT_MIP_LINEAR,
COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT,
COMPARISON_MIN_POINT_MAG_MIP_LINEAR,
COMPARISON_MIN_LINEAR_MAG_MIP_POINT,
COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
COMPARISON_MIN_MAG_LINEAR_MIP_POINT,
COMPARISON_MIN_MAG_MIP_LINEAR,
COMPARISON_ANISOTROPIC,
MINIMUM_MIN_MAG_MIP_POINT,
MINIMUM_MIN_MAG_POINT_MIP_LINEAR,
MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
MINIMUM_MIN_POINT_MAG_MIP_LINEAR,
MINIMUM_MIN_LINEAR_MAG_MIP_POINT,
MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
MINIMUM_MIN_MAG_LINEAR_MIP_POINT,
MINIMUM_MIN_MAG_MIP_LINEAR,
MINIMUM_ANISOTROPIC,
MAXIMUM_MIN_MAG_MIP_POINT,
MAXIMUM_MIN_MAG_POINT_MIP_LINEAR,
MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
MAXIMUM_MIN_POINT_MAG_MIP_LINEAR,
MAXIMUM_MIN_LINEAR_MAG_MIP_POINT,
MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
MAXIMUM_MIN_MAG_LINEAR_MIP_POINT,
MAXIMUM_MIN_MAG_MIP_LINEAR,
MAXIMUM_ANISOTROPIC,
};
enum class SamplerBorderColor
{
TRANSPARENT_BLACK,
OPAQUE_BLACK,
OPAQUE_WHITE,
};
enum class Format
{
UNKNOWN,
R32G32B32A32_FLOAT,
R32G32B32A32_UINT,
R32G32B32A32_SINT,
R32G32B32_FLOAT,
R32G32B32_UINT,
R32G32B32_SINT,
R16G16B16A16_FLOAT,
R16G16B16A16_UNORM,
R16G16B16A16_UINT,
R16G16B16A16_SNORM,
R16G16B16A16_SINT,
R32G32_FLOAT,
R32G32_UINT,
R32G32_SINT,
R32G8X24_TYPELESS, // depth (32-bit) + stencil (8-bit) + shader resource (32-bit)
D32_FLOAT_S8X24_UINT, // depth (32-bit) + stencil (8-bit)
R10G10B10A2_UNORM,
R10G10B10A2_UINT,
R11G11B10_FLOAT,
R8G8B8A8_UNORM,
R8G8B8A8_UNORM_SRGB,
R8G8B8A8_UINT,
R8G8B8A8_SNORM,
R8G8B8A8_SINT,
B8G8R8A8_UNORM,
B8G8R8A8_UNORM_SRGB,
R16G16_FLOAT,
R16G16_UNORM,
R16G16_UINT,
R16G16_SNORM,
R16G16_SINT,
R32_TYPELESS, // depth (32-bit) + shader resource (32-bit)
D32_FLOAT, // depth (32-bit)
R32_FLOAT,
R32_UINT,
R32_SINT,
R24G8_TYPELESS, // depth (24-bit) + stencil (8-bit) + shader resource (24-bit)
D24_UNORM_S8_UINT, // depth (24-bit) + stencil (8-bit)
R8G8_UNORM,
R8G8_UINT,
R8G8_SNORM,
R8G8_SINT,
R16_TYPELESS, // depth (16-bit) + shader resource (16-bit)
R16_FLOAT,
D16_UNORM, // depth (16-bit)
R16_UNORM,
R16_UINT,
R16_SNORM,
R16_SINT,
R8_UNORM,
R8_UINT,
R8_SNORM,
R8_SINT,
BC1_UNORM,
BC1_UNORM_SRGB,
BC2_UNORM,
BC2_UNORM_SRGB,
BC3_UNORM,
BC3_UNORM_SRGB,
BC4_UNORM,
BC4_SNORM,
BC5_UNORM,
BC5_SNORM,
BC6H_UF16,
BC6H_SF16,
BC7_UNORM,
BC7_UNORM_SRGB
};
enum class GpuQueryType
{
TIMESTAMP, // retrieve time point of gpu execution
OCCLUSION, // how many samples passed depth test?
OCCLUSION_BINARY, // depth test passed or not?
};
enum class IndexBufferFormat
{
UINT16,
UINT32,
};
enum class SubresourceType
{
SRV, // shader resource view
UAV, // unordered access view
RTV, // render target view
DSV, // depth stencil view
};
enum class ShadingRate
{
RATE_1X1, // Default/full shading rate
RATE_1X2,
RATE_2X1,
RATE_2X2,
RATE_2X4,
RATE_4X2,
RATE_4X4,
RATE_INVALID
};
enum class PredicationOp
{
EQUAL_ZERO,
NOT_EQUAL_ZERO,
};
// Flags ////////////////////////////////////////////
enum class ColorWrite
{
DISABLE = 0,
ENABLE_RED = 1 << 0,
ENABLE_GREEN = 1 << 1,
ENABLE_BLUE = 1 << 2,
ENABLE_ALPHA = 1 << 3,
ENABLE_ALL = ~0,
};
enum class BindFlag
{
NONE = 0,
VERTEX_BUFFER = 1 << 0,
INDEX_BUFFER = 1 << 1,
CONSTANT_BUFFER = 1 << 2,
SHADER_RESOURCE = 1 << 3,
RENDER_TARGET = 1 << 4,
DEPTH_STENCIL = 1 << 5,
UNORDERED_ACCESS = 1 << 6,
SHADING_RATE = 1 << 7,
};
enum class ResourceMiscFlag
{
NONE = 0,
TEXTURECUBE = 1 << 0,
INDIRECT_ARGS = 1 << 1,
BUFFER_RAW = 1 << 2,
BUFFER_STRUCTURED = 1 << 3,
RAY_TRACING = 1 << 4,
PREDICATION = 1 << 5,
};
enum class GraphicsDeviceCapability
{
NONE = 0,
TESSELLATION = 1 << 0,
CONSERVATIVE_RASTERIZATION = 1 << 1,
RASTERIZER_ORDERED_VIEWS = 1 << 2,
UAV_LOAD_FORMAT_COMMON = 1 << 3, // eg: R16G16B16A16_FLOAT, R8G8B8A8_UNORM and more common ones
UAV_LOAD_FORMAT_R11G11B10_FLOAT = 1 << 4,
RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS = 1 << 5,
VARIABLE_RATE_SHADING = 1 << 6,
VARIABLE_RATE_SHADING_TIER2 = 1 << 7,
MESH_SHADER = 1 << 8,
RAYTRACING = 1 << 9,
PREDICATION = 1 << 10,
SAMPLER_MINMAX = 1 << 11,
DEPTH_BOUNDS_TEST = 1 << 12,
};
enum class ResourceState
{
// Common resource states:
UNDEFINED = 0, // invalid state (don't preserve contents)
SHADER_RESOURCE = 1 << 0, // shader resource, read only
SHADER_RESOURCE_COMPUTE = 1 << 1, // shader resource, read only, non-pixel shader
UNORDERED_ACCESS = 1 << 2, // shader resource, write enabled
COPY_SRC = 1 << 3, // copy from
COPY_DST = 1 << 4, // copy to
// Texture specific resource states:
RENDERTARGET = 1 << 5, // render target, write enabled
DEPTHSTENCIL = 1 << 6, // depth stencil, write enabled
DEPTHSTENCIL_READONLY = 1 << 7, // depth stencil, read only
SHADING_RATE_SOURCE = 1 << 8, // shading rate control per tile
// GPUBuffer specific resource states:
VERTEX_BUFFER = 1 << 9, // vertex buffer, read only
INDEX_BUFFER = 1 << 10, // index buffer, read only
CONSTANT_BUFFER = 1 << 11, // constant buffer, read only
INDIRECT_ARGUMENT = 1 << 12, // argument buffer to DrawIndirect() or DispatchIndirect()
RAYTRACING_ACCELERATION_STRUCTURE = 1 << 13, // acceleration structure storage or scratch
PREDICATION = 1 << 14 // storage for predication comparison value
};
enum class ColorSpace
{
SRGB, // SDR color space (8 or 10 bits per channel)
HDR10_ST2084, // HDR10 color space (10 bits per channel)
HDR_LINEAR, // HDR color space (16 bits per channel)
};
// Descriptor structs:
struct Viewport
{
float top_left_x = 0;
float top_left_y = 0;
float width = 0;
float height = 0;
float min_depth = 0;
float max_depth = 1;
};
struct InputLayout
{
static const uint32_t APPEND_ALIGNED_ELEMENT = ~0u; // automatically figure out AlignedByteOffset depending on Format
struct Element
{
std::string semantic_name;
uint32_t semantic_index = 0;
Format format = Format::UNKNOWN;
uint32_t input_slot = 0;
uint32_t aligned_byte_offset = APPEND_ALIGNED_ELEMENT;
InputClassification input_slot_class = InputClassification::PER_VERTEX_DATA;
};
wi::vector<Element> elements;
};
union ClearValue
{
float color[4];
struct ClearDepthStencil
{
float depth;
uint32_t stencil;
} depth_stencil;
};
struct TextureDesc
{
enum class Type
{
TEXTURE_1D,
TEXTURE_2D,
TEXTURE_3D,
} type = Type::TEXTURE_2D;
uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 0;
uint32_t array_size = 1;
uint32_t mip_levels = 1;
Format format = Format::UNKNOWN;
uint32_t sample_count = 1;
Usage usage = Usage::DEFAULT;
BindFlag bind_flags = BindFlag::NONE;
ResourceMiscFlag misc_flags = ResourceMiscFlag::NONE;
ClearValue clear = {};
ResourceState layout = ResourceState::SHADER_RESOURCE;
};
struct SamplerDesc
{
Filter filter = Filter::MIN_MAG_MIP_POINT;
TextureAddressMode address_u = TextureAddressMode::CLAMP;
TextureAddressMode address_v = TextureAddressMode::CLAMP;
TextureAddressMode address_w = TextureAddressMode::CLAMP;
float mip_lod_bias = 0;
uint32_t max_anisotropy = 0;
ComparisonFunc comparison_func = ComparisonFunc::NEVER;
SamplerBorderColor border_color = SamplerBorderColor::TRANSPARENT_BLACK;
float min_lod = 0;
float max_lod = std::numeric_limits<float>::max();
};
struct RasterizerState
{
FillMode fill_mode = FillMode::SOLID;
CullMode cull_mode = CullMode::NONE;
bool front_counter_clockwise = false;
int32_t depth_bias = 0;
float depth_bias_clamp = 0;
float slope_scaled_depth_bias = 0;
bool depth_clip_enable = false;
bool multisample_enable = false;
bool antialiased_line_enable = false;
bool conservative_rasterization_enable = false;
uint32_t forced_sample_count = 0;
};
struct DepthStencilState
{
bool depth_enable = false;
DepthWriteMask depth_write_mask = DepthWriteMask::ZERO;
ComparisonFunc depth_func = ComparisonFunc::NEVER;
bool stencil_enable = false;
uint8_t stencil_read_mask = 0xff;
uint8_t stencil_write_mask = 0xff;
struct DepthStencilOp
{
StencilOp stencil_fail_op = StencilOp::KEEP;
StencilOp stencil_depth_fail_op = StencilOp::KEEP;
StencilOp stencil_pass_op = StencilOp::KEEP;
ComparisonFunc stencil_func = ComparisonFunc::NEVER;
};
DepthStencilOp front_face;
DepthStencilOp back_face;
bool depth_bounds_test_enable = false;
};
struct BlendState
{
bool alpha_to_coverage_enable = false;
bool independent_blend_enable = false;
struct RenderTargetBlendState
{
bool blend_enable = false;
Blend src_blend = Blend::SRC_ALPHA;
Blend dest_blend = Blend::INV_SRC_ALPHA;
BlendOp blend_op = BlendOp::ADD;
Blend src_blend_alpha = Blend::ONE;
Blend dest_blend_alpha = Blend::ONE;
BlendOp blend_op_alpha = BlendOp::ADD;
ColorWrite render_target_write_mask = ColorWrite::ENABLE_ALL;
};
RenderTargetBlendState render_target[8];
};
struct GPUBufferDesc
{
uint64_t size = 0;
Usage usage = Usage::DEFAULT;
BindFlag bind_flags = BindFlag::NONE;
ResourceMiscFlag misc_flags = ResourceMiscFlag::NONE;
uint32_t stride = 0; // only needed for structured buffer types!
Format format = Format::UNKNOWN; // only needed for typed buffer!
};
struct GPUQueryHeapDesc
{
GpuQueryType type = GpuQueryType::TIMESTAMP;
uint32_t query_count = 0;
};
struct PipelineStateDesc
{
const Shader* vs = nullptr;
const Shader* ps = nullptr;
const Shader* hs = nullptr;
const Shader* ds = nullptr;
const Shader* gs = nullptr;
const Shader* ms = nullptr;
const Shader* as = nullptr;
const BlendState* bs = nullptr;
const RasterizerState* rs = nullptr;
const DepthStencilState* dss = nullptr;
const InputLayout* il = nullptr;
PrimitiveTopology pt = PrimitiveTopology::TRIANGLELIST;
uint32_t patch_control_points = 3;
uint32_t sample_mask = 0xFFFFFFFF;
};
struct GPUBarrier
{
enum class Type
{
MEMORY, // UAV accesses
IMAGE, // image layout transition
BUFFER, // buffer state transition
} type = Type::MEMORY;
struct Memory
{
const GPUResource* resource;
};
struct Image
{
const Texture* texture;
ResourceState layout_before;
ResourceState layout_after;
int mip;
int slice;
};
struct Buffer
{
const GPUBuffer* buffer;
ResourceState state_before;
ResourceState state_after;
};
union
{
Memory memory;
Image image;
Buffer buffer;
};
static GPUBarrier Memory(const GPUResource* resource = nullptr)
{
GPUBarrier barrier;
barrier.type = Type::MEMORY;
barrier.memory.resource = resource;
return barrier;
}
static GPUBarrier Image(const Texture* texture, ResourceState before, ResourceState after,
int mip = -1, int slice = -1)
{
GPUBarrier barrier;
barrier.type = Type::IMAGE;
barrier.image.texture = texture;
barrier.image.layout_before = before;
barrier.image.layout_after = after;
barrier.image.mip = mip;
barrier.image.slice = slice;
return barrier;
}
static GPUBarrier Buffer(const GPUBuffer* buffer, ResourceState before, ResourceState after)
{
GPUBarrier barrier;
barrier.type = Type::BUFFER;
barrier.buffer.buffer = buffer;
barrier.buffer.state_before = before;
barrier.buffer.state_after = after;
return barrier;
}
};
struct RenderPassAttachment
{
enum class Type
{
RENDERTARGET,
DEPTH_STENCIL,
RESOLVE,
SHADING_RATE_SOURCE
} type = Type::RENDERTARGET;
enum class LoadOp
{
LOAD,
CLEAR,
DONTCARE,
} loadop = LoadOp::LOAD;
const Texture* texture = nullptr;
int subresource = -1;
enum class StoreOp
{
STORE,
DONTCARE,
} storeop = StoreOp::STORE;
ResourceState initial_layout = ResourceState::UNDEFINED; // layout before the render pass
ResourceState subpass_layout = ResourceState::UNDEFINED; // layout within the render pass
ResourceState final_layout = ResourceState::UNDEFINED; // layout after the render pass
static RenderPassAttachment RenderTarget(
const Texture* resource = nullptr,
LoadOp load_op = LoadOp::LOAD,
StoreOp store_op = StoreOp::STORE,
ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
ResourceState subpass_layout = ResourceState::RENDERTARGET,
ResourceState final_layout = ResourceState::SHADER_RESOURCE
)
{
RenderPassAttachment attachment;
attachment.type = Type::RENDERTARGET;
attachment.texture = resource;
attachment.loadop = load_op;
attachment.storeop = store_op;
attachment.initial_layout = initial_layout;
attachment.subpass_layout = subpass_layout;
attachment.final_layout = final_layout;
return attachment;
}
static RenderPassAttachment DepthStencil(
const Texture* resource = nullptr,
LoadOp load_op = LoadOp::LOAD,
StoreOp store_op = StoreOp::STORE,
ResourceState initial_layout = ResourceState::DEPTHSTENCIL,
ResourceState subpass_layout = ResourceState::DEPTHSTENCIL,
ResourceState final_layout = ResourceState::DEPTHSTENCIL
)
{
RenderPassAttachment attachment;
attachment.type = Type::DEPTH_STENCIL;
attachment.texture = resource;
attachment.loadop = load_op;
attachment.storeop = store_op;
attachment.initial_layout = initial_layout;
attachment.subpass_layout = subpass_layout;
attachment.final_layout = final_layout;
return attachment;
}
static RenderPassAttachment Resolve(
const Texture* resource = nullptr,
ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
ResourceState final_layout = ResourceState::SHADER_RESOURCE
)
{
RenderPassAttachment attachment;
attachment.type = Type::RESOLVE;
attachment.texture = resource;
attachment.initial_layout = initial_layout;
attachment.final_layout = final_layout;
return attachment;
}
static RenderPassAttachment ShadingRateSource(
const Texture* resource = nullptr,
ResourceState initial_layout = ResourceState::SHADING_RATE_SOURCE,
ResourceState final_layout = ResourceState::SHADING_RATE_SOURCE
)
{
RenderPassAttachment attachment;
attachment.type = Type::SHADING_RATE_SOURCE;
attachment.texture = resource;
attachment.initial_layout = initial_layout;
attachment.subpass_layout = ResourceState::SHADING_RATE_SOURCE;
attachment.final_layout = final_layout;
return attachment;
}
};
struct RenderPassDesc
{
enum class Flags
{
EMPTY = 0,
ALLOW_UAV_WRITES = 1 << 0,
};
Flags flags = Flags::EMPTY;
wi::vector<RenderPassAttachment> attachments;
};
struct SwapChainDesc
{
uint32_t width = 0;
uint32_t height = 0;
uint32_t buffer_count = 2;
Format format = Format::R10G10B10A2_UNORM;
bool fullscreen = false;
bool vsync = true;
float clear_color[4] = { 0,0,0,1 };
bool allow_hdr = true;
};
struct IndirectDrawArgsInstanced
{
uint32_t vertex_count_per_instance = 0;
uint32_t instance_count = 0;
uint32_t start_vertex_location = 0;
uint32_t start_instance_location = 0;
};
struct IndirectDrawArgsIndexedInstanced
{
uint32_t index_count_per_instance = 0;
uint32_t instance_count = 0;
uint32_t start_index_location = 0;
int32_t base_vertex_location = 0;
uint32_t start_instance_location = 0;
};
struct IndirectDispatchArgs
{
uint32_t thread_group_count_x = 0;
uint32_t thread_group_count_y = 0;
uint32_t thread_group_count_z = 0;
};
struct SubresourceData
{
const void *data_ptr = nullptr;
uint32_t row_pitch = 0;
uint32_t slice_pitch = 0;
};
struct Rect
{
int32_t left = 0;
int32_t top = 0;
int32_t right = 0;
int32_t bottom = 0;
};
// Resources:
struct GraphicsDeviceChild
{
std::shared_ptr<void> internal_state;
inline bool IsValid() const { return internal_state.get() != nullptr; }
};
struct Sampler : public GraphicsDeviceChild
{
SamplerDesc desc;
const SamplerDesc& GetDesc() const { return desc; }
};
struct Shader : public GraphicsDeviceChild
{
ShaderStage stage = ShaderStage::Count;
};
struct GPUResource : public GraphicsDeviceChild
{
enum class Type
{
BUFFER,
TEXTURE,
RAYTRACING_ACCELERATION_STRUCTURE,
UNKNOWN_TYPE,
} type = Type::UNKNOWN_TYPE;
constexpr bool IsTexture() const { return type == Type::TEXTURE; }
constexpr bool IsBuffer() const { return type == Type::BUFFER; }
constexpr bool IsAccelerationStructure() const { return type == Type::RAYTRACING_ACCELERATION_STRUCTURE; }
void* mapped_data = nullptr;
uint32_t mapped_rowpitch = 0;
};
struct GPUBuffer : public GPUResource
{
GPUBufferDesc desc;
constexpr const GPUBufferDesc& GetDesc() const { return desc; }
};
struct Texture : public GPUResource
{
TextureDesc desc;
constexpr const TextureDesc& GetDesc() const { return desc; }
};
struct GPUQueryHeap : public GraphicsDeviceChild
{
GPUQueryHeapDesc desc;
constexpr const GPUQueryHeapDesc& GetDesc() const { return desc; }
};
struct PipelineState : public GraphicsDeviceChild
{
size_t hash = 0;
PipelineStateDesc desc;
constexpr const PipelineStateDesc& GetDesc() const { return desc; }
};
struct RenderPass : public GraphicsDeviceChild
{
size_t hash = 0;
RenderPassDesc desc;
constexpr const RenderPassDesc& GetDesc() const { return desc; }
};
struct SwapChain : public GraphicsDeviceChild
{
SwapChainDesc desc;
constexpr const SwapChainDesc& GetDesc() const { return desc; }
};
struct RaytracingAccelerationStructureDesc
{
enum Flags
{
FLAG_EMPTY = 0,
FLAG_ALLOW_UPDATE = 1 << 0,
FLAG_ALLOW_COMPACTION = 1 << 1,
FLAG_PREFER_FAST_TRACE = 1 << 2,
FLAG_PREFER_FAST_BUILD = 1 << 3,
FLAG_MINIMIZE_MEMORY = 1 << 4,
};
uint32_t flags = FLAG_EMPTY;
enum class Type
{
BOTTOMLEVEL,
TOPLEVEL,
} type = Type::BOTTOMLEVEL;
struct BottomLevel
{
struct Geometry
{
enum FLAGS
{
FLAG_EMPTY = 0,
FLAG_OPAQUE = 1 << 0,
FLAG_NO_DUPLICATE_ANYHIT_INVOCATION = 1 << 1,
FLAG_USE_TRANSFORM = 1 << 2,
};
uint32_t flags = FLAG_EMPTY;
enum class Type
{
TRIANGLES,
PROCEDURAL_AABBS,
} type = Type::TRIANGLES;
struct Triangles
{
GPUBuffer vertex_buffer;
GPUBuffer index_buffer;
uint32_t index_count = 0;
uint64_t index_offset = 0;
uint32_t vertex_count = 0;
uint64_t vertex_byte_offset = 0;
uint32_t vertex_stride = 0;
IndexBufferFormat index_format = IndexBufferFormat::UINT32;
Format vertex_format = Format::R32G32B32_FLOAT;
GPUBuffer transform_3x4_buffer;
uint32_t transform_3x4_buffer_offset = 0;
} triangles;
struct Procedural_AABBs
{
GPUBuffer aabb_buffer;
uint32_t offset = 0;
uint32_t count = 0;
uint32_t stride = 0;
} aabbs;
};
wi::vector<Geometry> geometries;
} bottom_level;
struct TopLevel
{
struct Instance
{
enum FLAGS
{
FLAG_EMPTY = 0,
FLAG_TRIANGLE_CULL_DISABLE = 1 << 0,
FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE = 1 << 1,
FLAG_FORCE_OPAQUE = 1 << 2,
FLAG_FORCE_NON_OPAQUE = 1 << 3,
};
float transform[3][4];
uint32_t instance_id : 24;
uint32_t instance_mask : 8;
uint32_t instance_contribution_to_hit_group_index : 24;
uint32_t flags : 8;
const GPUResource* bottom_level = nullptr;
};
GPUBuffer instance_buffer;
uint32_t offset = 0;
uint32_t count = 0;
} top_level;
};
struct RaytracingAccelerationStructure : public GPUResource
{
RaytracingAccelerationStructureDesc desc;
constexpr const RaytracingAccelerationStructureDesc& GetDesc() const { return desc; }
};
struct ShaderLibrary
{
enum class Type
{
RAYGENERATION,
MISS,
CLOSESTHIT,
ANYHIT,
INTERSECTION,
} type = Type::RAYGENERATION;
const Shader* shader = nullptr;
std::string function_name;
};
struct ShaderHitGroup
{
enum class Type
{
GENERAL, // raygen or miss
TRIANGLES,
PROCEDURAL,
} type = Type::TRIANGLES;
std::string name;
uint32_t general_shader = ~0u;
uint32_t closest_hit_shader = ~0u;
uint32_t any_hit_shader = ~0u;
uint32_t intersection_shader = ~0u;
};
struct RaytracingPipelineStateDesc
{
wi::vector<ShaderLibrary> shader_libraries;
wi::vector<ShaderHitGroup> hit_groups;
uint32_t max_trace_recursion_depth = 1;
uint32_t max_attribute_size_in_bytes = 0;
uint32_t max_payload_size_in_bytes = 0;
};
struct RaytracingPipelineState : public GraphicsDeviceChild
{
RaytracingPipelineStateDesc desc;
constexpr const RaytracingPipelineStateDesc& GetDesc() const { return desc; }
};
struct ShaderTable
{
const GPUBuffer* buffer = nullptr;
uint64_t offset = 0;
uint64_t size = 0;
uint64_t stride = 0;
};
struct DispatchRaysDesc
{
ShaderTable ray_generation;
ShaderTable miss;
ShaderTable hit_group;
ShaderTable callable;
uint32_t width = 1;
uint32_t height = 1;
uint32_t depth = 1;
};
constexpr bool IsFormatUnorm(Format format)
{
switch (format)
{
case Format::R16G16B16A16_UNORM:
case Format::R10G10B10A2_UNORM:
case Format::R8G8B8A8_UNORM:
case Format::R8G8B8A8_UNORM_SRGB:
case Format::B8G8R8A8_UNORM:
case Format::B8G8R8A8_UNORM_SRGB:
case Format::R16G16_UNORM:
case Format::D24_UNORM_S8_UINT:
case Format::R8G8_UNORM:
case Format::D16_UNORM:
case Format::R16_UNORM:
case Format::R8_UNORM:
return true;
}
return false;
}
constexpr bool IsFormatBlockCompressed(Format format)
{
switch (format)
{
case Format::BC1_UNORM:
case Format::BC1_UNORM_SRGB:
case Format::BC2_UNORM:
case Format::BC2_UNORM_SRGB:
case Format::BC3_UNORM:
case Format::BC3_UNORM_SRGB:
case Format::BC4_UNORM:
case Format::BC4_SNORM:
case Format::BC5_UNORM:
case Format::BC5_SNORM:
case Format::BC6H_UF16:
case Format::BC6H_SF16:
case Format::BC7_UNORM:
case Format::BC7_UNORM_SRGB:
return true;
}
return false;
}
constexpr bool IsFormatStencilSupport(Format format)
{
switch (format)
{
case Format::R32G8X24_TYPELESS:
case Format::D32_FLOAT_S8X24_UINT:
case Format::R24G8_TYPELESS:
case Format::D24_UNORM_S8_UINT:
return true;
}
return false;
}
constexpr uint32_t GetFormatBlockSize(Format format)
{
if(IsFormatBlockCompressed(format))
{
return 4u;
}
return 1u;
}
constexpr uint32_t GetFormatStride(Format format)
{
switch (format)
{
case Format::BC1_UNORM:
case Format::BC1_UNORM_SRGB:
case Format::BC4_SNORM:
case Format::BC4_UNORM:
return 8u;
case Format::R32G32B32A32_FLOAT:
case Format::R32G32B32A32_UINT:
case Format::R32G32B32A32_SINT:
case Format::BC2_UNORM:
case Format::BC2_UNORM_SRGB:
case Format::BC3_UNORM:
case Format::BC3_UNORM_SRGB:
case Format::BC5_SNORM:
case Format::BC5_UNORM:
case Format::BC6H_UF16:
case Format::BC6H_SF16:
case Format::BC7_UNORM:
case Format::BC7_UNORM_SRGB:
return 16u;
case Format::R32G32B32_FLOAT:
case Format::R32G32B32_UINT:
case Format::R32G32B32_SINT:
return 12u;
case Format::R16G16B16A16_FLOAT:
case Format::R16G16B16A16_UNORM:
case Format::R16G16B16A16_UINT:
case Format::R16G16B16A16_SNORM:
case Format::R16G16B16A16_SINT:
return 8u;
case Format::R32G32_FLOAT:
case Format::R32G32_UINT:
case Format::R32G32_SINT:
case Format::R32G8X24_TYPELESS:
case Format::D32_FLOAT_S8X24_UINT:
return 8u;
case Format::R10G10B10A2_UNORM:
case Format::R10G10B10A2_UINT:
case Format::R11G11B10_FLOAT:
case Format::R8G8B8A8_UNORM:
case Format::R8G8B8A8_UNORM_SRGB:
case Format::R8G8B8A8_UINT:
case Format::R8G8B8A8_SNORM:
case Format::R8G8B8A8_SINT:
case Format::B8G8R8A8_UNORM:
case Format::B8G8R8A8_UNORM_SRGB:
case Format::R16G16_FLOAT:
case Format::R16G16_UNORM:
case Format::R16G16_UINT:
case Format::R16G16_SNORM:
case Format::R16G16_SINT:
case Format::R32_TYPELESS:
case Format::D32_FLOAT:
case Format::R32_FLOAT:
case Format::R32_UINT:
case Format::R32_SINT:
case Format::R24G8_TYPELESS:
case Format::D24_UNORM_S8_UINT:
return 4u;
case Format::R8G8_UNORM:
case Format::R8G8_UINT:
case Format::R8G8_SNORM:
case Format::R8G8_SINT:
case Format::R16_TYPELESS:
case Format::R16_FLOAT:
case Format::D16_UNORM:
case Format::R16_UNORM:
case Format::R16_UINT:
case Format::R16_SNORM:
case Format::R16_SINT:
return 2u;
case Format::R8_UNORM:
case Format::R8_UINT:
case Format::R8_SNORM:
case Format::R8_SINT:
return 1u;
default:
assert(0); // didn't catch format!
break;
}
return 16u;
}
constexpr uint32_t AlignTo(uint32_t value, uint32_t alignment)
{
return ((value + alignment - 1) / alignment) * alignment;
}
constexpr uint64_t AlignTo(uint64_t value, uint64_t alignment)
{
return ((value + alignment - 1) / alignment) * alignment;
}
}
template<>
struct enable_bitmask_operators<wi::graphics::ColorWrite> {
static const bool enable = true;
};
template<>
struct enable_bitmask_operators<wi::graphics::BindFlag> {
static const bool enable = true;
};
template<>
struct enable_bitmask_operators<wi::graphics::ResourceMiscFlag> {
static const bool enable = true;
};
template<>
struct enable_bitmask_operators<wi::graphics::GraphicsDeviceCapability> {
static const bool enable = true;
};
template<>
struct enable_bitmask_operators<wi::graphics::ResourceState> {
static const bool enable = true;
};
template<>
struct enable_bitmask_operators<wi::graphics::RenderPassDesc::Flags> {
static const bool enable = true;
};