432 lines
15 KiB
C++
432 lines
15 KiB
C++
#pragma once
|
|
|
|
#include "foundation/result.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <span>
|
|
|
|
namespace pp::renderer {
|
|
|
|
constexpr std::uint32_t max_texture_dimension = 32768;
|
|
constexpr std::uint32_t max_texture_mip_levels = 16;
|
|
constexpr std::uint32_t max_mesh_vertices = 16777216;
|
|
constexpr std::uint32_t max_texture_slots = 32;
|
|
constexpr std::uint64_t max_texture_bytes = 1024ULL * 1024ULL * 1024ULL;
|
|
constexpr std::size_t max_shader_source_bytes = 4ULL * 1024ULL * 1024ULL;
|
|
constexpr std::size_t max_shader_uniform_bytes = 64ULL * 1024ULL;
|
|
constexpr std::size_t max_trace_label_bytes = 256;
|
|
constexpr std::size_t max_resource_label_bytes = 256;
|
|
|
|
enum class TextureFormat : std::uint8_t {
|
|
rgba8,
|
|
r8,
|
|
depth24_stencil8,
|
|
};
|
|
|
|
enum class TextureUsage : std::uint32_t {
|
|
none = 0,
|
|
sampled = 1U << 0U,
|
|
render_target = 1U << 1U,
|
|
upload_destination = 1U << 2U,
|
|
readback_source = 1U << 3U,
|
|
copy_source = 1U << 4U,
|
|
copy_destination = 1U << 5U,
|
|
};
|
|
|
|
enum class TextureState : std::uint8_t {
|
|
undefined,
|
|
shader_read,
|
|
render_target,
|
|
upload_destination,
|
|
copy_source,
|
|
copy_destination,
|
|
readback_source,
|
|
present,
|
|
};
|
|
|
|
[[nodiscard]] constexpr TextureUsage operator|(TextureUsage lhs, TextureUsage rhs) noexcept
|
|
{
|
|
return static_cast<TextureUsage>(
|
|
static_cast<std::uint32_t>(lhs) | static_cast<std::uint32_t>(rhs));
|
|
}
|
|
|
|
[[nodiscard]] constexpr TextureUsage operator&(TextureUsage lhs, TextureUsage rhs) noexcept
|
|
{
|
|
return static_cast<TextureUsage>(
|
|
static_cast<std::uint32_t>(lhs) & static_cast<std::uint32_t>(rhs));
|
|
}
|
|
|
|
constexpr TextureUsage& operator|=(TextureUsage& lhs, TextureUsage rhs) noexcept
|
|
{
|
|
lhs = lhs | rhs;
|
|
return lhs;
|
|
}
|
|
|
|
struct Extent2D {
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
};
|
|
|
|
struct TextureDesc {
|
|
Extent2D extent;
|
|
TextureFormat format = TextureFormat::rgba8;
|
|
std::uint32_t mip_levels = 1;
|
|
TextureUsage usage = TextureUsage::sampled
|
|
| TextureUsage::upload_destination
|
|
| TextureUsage::readback_source
|
|
| TextureUsage::copy_source
|
|
| TextureUsage::copy_destination;
|
|
const char* debug_name = "";
|
|
};
|
|
|
|
struct ReadbackRegion {
|
|
std::uint32_t x = 0;
|
|
std::uint32_t y = 0;
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
};
|
|
|
|
struct Viewport {
|
|
std::int32_t x = 0;
|
|
std::int32_t y = 0;
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
float min_depth = 0.0F;
|
|
float max_depth = 1.0F;
|
|
};
|
|
|
|
struct ScissorRect {
|
|
bool enabled = false;
|
|
std::int32_t x = 0;
|
|
std::int32_t y = 0;
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
};
|
|
|
|
struct ClearColor {
|
|
float r = 0.0F;
|
|
float g = 0.0F;
|
|
float b = 0.0F;
|
|
float a = 0.0F;
|
|
};
|
|
|
|
struct RenderPassDesc {
|
|
bool clear_color_enabled = true;
|
|
ClearColor clear_color;
|
|
bool clear_depth_enabled = false;
|
|
float clear_depth = 1.0F;
|
|
bool clear_stencil_enabled = false;
|
|
std::uint8_t clear_stencil = 0;
|
|
};
|
|
|
|
enum class PrimitiveTopology : std::uint8_t {
|
|
triangles,
|
|
triangle_strip,
|
|
lines,
|
|
};
|
|
|
|
enum class BlitFilter : std::uint8_t {
|
|
nearest,
|
|
linear,
|
|
};
|
|
|
|
enum class PaintFeedbackPath : std::uint8_t {
|
|
none,
|
|
framebuffer_fetch,
|
|
ping_pong_textures,
|
|
};
|
|
|
|
enum class BlendFactor : std::uint8_t {
|
|
zero,
|
|
one,
|
|
source_alpha,
|
|
one_minus_source_alpha,
|
|
destination_alpha,
|
|
one_minus_destination_alpha,
|
|
};
|
|
|
|
enum class BlendOp : std::uint8_t {
|
|
add,
|
|
subtract,
|
|
reverse_subtract,
|
|
};
|
|
|
|
enum class CompareOp : std::uint8_t {
|
|
never,
|
|
less,
|
|
equal,
|
|
less_or_equal,
|
|
greater,
|
|
not_equal,
|
|
greater_or_equal,
|
|
always,
|
|
};
|
|
|
|
enum class SamplerFilter : std::uint8_t {
|
|
nearest,
|
|
linear,
|
|
};
|
|
|
|
enum class SamplerAddressMode : std::uint8_t {
|
|
clamp_to_edge,
|
|
repeat,
|
|
mirrored_repeat,
|
|
clamp_to_border,
|
|
};
|
|
|
|
struct BlendState {
|
|
bool enabled = false;
|
|
BlendFactor source_color = BlendFactor::one;
|
|
BlendFactor destination_color = BlendFactor::zero;
|
|
BlendOp color_op = BlendOp::add;
|
|
BlendFactor source_alpha = BlendFactor::one;
|
|
BlendFactor destination_alpha = BlendFactor::zero;
|
|
BlendOp alpha_op = BlendOp::add;
|
|
bool write_r = true;
|
|
bool write_g = true;
|
|
bool write_b = true;
|
|
bool write_a = true;
|
|
};
|
|
|
|
struct DepthState {
|
|
bool test_enabled = false;
|
|
bool write_enabled = false;
|
|
CompareOp compare = CompareOp::less_or_equal;
|
|
};
|
|
|
|
struct SamplerDesc {
|
|
SamplerFilter min_filter = SamplerFilter::linear;
|
|
SamplerFilter mag_filter = SamplerFilter::linear;
|
|
SamplerFilter mip_filter = SamplerFilter::linear;
|
|
SamplerAddressMode address_u = SamplerAddressMode::clamp_to_edge;
|
|
SamplerAddressMode address_v = SamplerAddressMode::clamp_to_edge;
|
|
SamplerAddressMode address_w = SamplerAddressMode::clamp_to_edge;
|
|
};
|
|
|
|
struct MeshDesc {
|
|
std::uint32_t vertex_count = 0;
|
|
std::uint32_t index_count = 0;
|
|
PrimitiveTopology topology = PrimitiveTopology::triangles;
|
|
const char* debug_name = "";
|
|
};
|
|
|
|
struct DrawDesc {
|
|
std::uint32_t first_vertex = 0;
|
|
std::uint32_t vertex_count = 0;
|
|
std::uint32_t first_index = 0;
|
|
std::uint32_t index_count = 0;
|
|
std::uint32_t instance_count = 1;
|
|
};
|
|
|
|
struct ShaderStageSource {
|
|
const char* entry_point = "main";
|
|
const char* source = nullptr;
|
|
std::size_t source_size = 0;
|
|
};
|
|
|
|
struct ShaderProgramDesc {
|
|
const char* debug_name = "";
|
|
ShaderStageSource vertex;
|
|
ShaderStageSource fragment;
|
|
};
|
|
|
|
struct RenderDeviceFeatures {
|
|
bool framebuffer_fetch = false;
|
|
bool explicit_texture_transitions = false;
|
|
bool texture_copy = false;
|
|
bool render_target_blit = false;
|
|
bool frame_capture = false;
|
|
bool float16_render_targets = false;
|
|
bool float32_render_targets = false;
|
|
bool float32_linear_filtering = false;
|
|
};
|
|
|
|
struct PaintFeedbackPlan {
|
|
PaintFeedbackPath path = PaintFeedbackPath::none;
|
|
TextureDesc target_desc {};
|
|
TextureDesc auxiliary_desc {};
|
|
std::uint64_t target_bytes = 0;
|
|
bool complex_blend = false;
|
|
bool reads_destination_color = false;
|
|
bool requires_auxiliary_texture = false;
|
|
bool requires_texture_copy = false;
|
|
bool requires_render_target_blit = false;
|
|
bool requires_explicit_transition = false;
|
|
};
|
|
|
|
class ITexture2D {
|
|
public:
|
|
virtual ~ITexture2D() = default;
|
|
[[nodiscard]] virtual TextureDesc desc() const noexcept = 0;
|
|
};
|
|
|
|
class IRenderTarget {
|
|
public:
|
|
virtual ~IRenderTarget() = default;
|
|
[[nodiscard]] virtual TextureDesc color_desc() const noexcept = 0;
|
|
};
|
|
|
|
class IShaderProgram {
|
|
public:
|
|
virtual ~IShaderProgram() = default;
|
|
[[nodiscard]] virtual const char* debug_name() const noexcept = 0;
|
|
};
|
|
|
|
class IMesh {
|
|
public:
|
|
virtual ~IMesh() = default;
|
|
[[nodiscard]] virtual MeshDesc desc() const noexcept = 0;
|
|
};
|
|
|
|
class IReadbackBuffer {
|
|
public:
|
|
virtual ~IReadbackBuffer() = default;
|
|
[[nodiscard]] virtual std::uint64_t size_bytes() const noexcept = 0;
|
|
};
|
|
|
|
class IRenderTrace {
|
|
public:
|
|
virtual ~IRenderTrace() = default;
|
|
[[nodiscard]] virtual pp::foundation::Status marker(const char* component, const char* name) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status begin_scope(const char* component, const char* name) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status end_scope() noexcept = 0;
|
|
};
|
|
|
|
class ICommandContext {
|
|
public:
|
|
virtual ~ICommandContext() = default;
|
|
[[nodiscard]] virtual pp::foundation::Status begin_render_pass(
|
|
IRenderTarget& target,
|
|
RenderPassDesc desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status set_viewport(Viewport viewport) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status set_scissor(ScissorRect scissor) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status set_blend_state(BlendState state) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status set_depth_state(DepthState state) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status bind_shader(IShaderProgram& shader) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status set_shader_uniform(
|
|
const char* name,
|
|
std::span<const std::byte> bytes) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status bind_texture(
|
|
std::uint32_t slot,
|
|
ITexture2D& texture) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status bind_sampler(
|
|
std::uint32_t slot,
|
|
SamplerDesc sampler) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status bind_mesh(IMesh& mesh) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status draw(DrawDesc desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status read_texture(
|
|
ITexture2D& texture,
|
|
ReadbackRegion region,
|
|
IReadbackBuffer& destination) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status upload_texture(
|
|
ITexture2D& texture,
|
|
ReadbackRegion region,
|
|
std::span<const std::byte> rgba_or_channel_bytes) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status generate_mipmaps(
|
|
ITexture2D& texture) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status transition_texture(
|
|
ITexture2D& texture,
|
|
TextureState before,
|
|
TextureState after) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status copy_texture(
|
|
ITexture2D& source,
|
|
ReadbackRegion source_region,
|
|
ITexture2D& destination,
|
|
ReadbackRegion destination_region) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status capture_frame(
|
|
IRenderTarget& target,
|
|
IReadbackBuffer& destination) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Status blit_render_target(
|
|
IRenderTarget& source,
|
|
ReadbackRegion source_region,
|
|
IRenderTarget& destination,
|
|
ReadbackRegion destination_region,
|
|
BlitFilter filter) noexcept = 0;
|
|
virtual void end_render_pass() noexcept = 0;
|
|
};
|
|
|
|
class IRenderDevice {
|
|
public:
|
|
virtual ~IRenderDevice() = default;
|
|
[[nodiscard]] virtual const char* backend_name() const noexcept = 0;
|
|
[[nodiscard]] virtual RenderDeviceFeatures features() const noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Result<std::unique_ptr<ITexture2D>> create_texture(
|
|
TextureDesc desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Result<std::unique_ptr<IRenderTarget>> create_render_target(
|
|
TextureDesc color_desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Result<std::unique_ptr<IShaderProgram>> create_shader_program(
|
|
ShaderProgramDesc desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Result<std::unique_ptr<IMesh>> create_mesh(
|
|
MeshDesc desc) noexcept = 0;
|
|
[[nodiscard]] virtual pp::foundation::Result<std::unique_ptr<IReadbackBuffer>> create_readback_buffer(
|
|
std::uint64_t size_bytes) noexcept = 0;
|
|
[[nodiscard]] virtual ICommandContext& immediate_context() noexcept = 0;
|
|
[[nodiscard]] virtual IRenderTrace* trace() noexcept = 0;
|
|
};
|
|
|
|
[[nodiscard]] std::uint32_t bytes_per_pixel(TextureFormat format) noexcept;
|
|
[[nodiscard]] std::uint32_t max_mip_levels_for_extent(Extent2D extent) noexcept;
|
|
[[nodiscard]] bool has_texture_usage(TextureUsage usage, TextureUsage required) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_extent(Extent2D extent) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_usage(TextureUsage usage) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_resource_label(const char* label) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_desc(TextureDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_viewport(Viewport viewport, Extent2D target_extent) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_scissor(ScissorRect scissor, Extent2D target_extent) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_render_pass_desc(RenderPassDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_blend_factor(BlendFactor factor) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_blend_op(BlendOp op) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_blend_state(BlendState state) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_compare_op(CompareOp op) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_depth_state(DepthState state) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_sampler_filter(SamplerFilter filter) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_sampler_address_mode(SamplerAddressMode mode) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_sampler_desc(SamplerDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_mesh_desc(MeshDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_draw_desc(MeshDesc mesh, DrawDesc draw) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_slot(std::uint32_t slot) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_shader_program_desc(ShaderProgramDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_shader_uniform_write(
|
|
const char* name,
|
|
std::span<const std::byte> bytes) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_trace_label(const char* component, const char* name) noexcept;
|
|
[[nodiscard]] pp::foundation::Result<std::uint64_t> texture_byte_size(TextureDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Result<std::uint64_t> readback_byte_size(
|
|
TextureDesc desc,
|
|
ReadbackRegion region) noexcept;
|
|
[[nodiscard]] pp::foundation::Result<std::uint64_t> frame_capture_byte_size(TextureDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_readback_region(TextureDesc desc, ReadbackRegion region) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_copy_descs(
|
|
TextureDesc source,
|
|
ReadbackRegion source_region,
|
|
TextureDesc destination,
|
|
ReadbackRegion destination_region) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_mipmap_generation_desc(TextureDesc desc) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_state(TextureState state) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_texture_transition_desc(
|
|
TextureDesc desc,
|
|
TextureState before,
|
|
TextureState after) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_blit_filter(BlitFilter filter) noexcept;
|
|
[[nodiscard]] pp::foundation::Status validate_blit_descs(
|
|
TextureDesc source,
|
|
TextureDesc destination) noexcept;
|
|
[[nodiscard]] pp::foundation::Result<PaintFeedbackPlan> plan_paint_feedback(
|
|
RenderDeviceFeatures features,
|
|
TextureDesc target_desc,
|
|
bool complex_blend) noexcept;
|
|
[[nodiscard]] const char* texture_format_name(TextureFormat format) noexcept;
|
|
[[nodiscard]] const char* texture_state_name(TextureState state) noexcept;
|
|
[[nodiscard]] const char* primitive_topology_name(PrimitiveTopology topology) noexcept;
|
|
[[nodiscard]] const char* blit_filter_name(BlitFilter filter) noexcept;
|
|
[[nodiscard]] const char* paint_feedback_path_name(PaintFeedbackPath path) noexcept;
|
|
[[nodiscard]] const char* blend_factor_name(BlendFactor factor) noexcept;
|
|
[[nodiscard]] const char* blend_op_name(BlendOp op) noexcept;
|
|
[[nodiscard]] const char* compare_op_name(CompareOp op) noexcept;
|
|
[[nodiscard]] const char* sampler_filter_name(SamplerFilter filter) noexcept;
|
|
[[nodiscard]] const char* sampler_address_mode_name(SamplerAddressMode mode) noexcept;
|
|
|
|
}
|