Add renderer texture transition contract
This commit is contained in:
@@ -435,6 +435,30 @@ pp::foundation::Status RecordingCommandContext::generate_mipmaps(ITexture2D& tex
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status RecordingCommandContext::transition_texture(
|
||||
ITexture2D& texture,
|
||||
TextureState before,
|
||||
TextureState after) noexcept
|
||||
{
|
||||
if (in_render_pass_) {
|
||||
return pp::foundation::Status::invalid_argument("texture transition must be outside a render pass");
|
||||
}
|
||||
|
||||
const auto desc = texture.desc();
|
||||
const auto desc_status = validate_texture_transition_desc(desc, before, after);
|
||||
if (!desc_status.ok()) {
|
||||
return desc_status;
|
||||
}
|
||||
|
||||
push_command(commands_, RecordedRenderCommand {
|
||||
.kind = RecordedRenderCommandKind::transition_texture,
|
||||
.texture_desc = desc,
|
||||
.before_state = before,
|
||||
.after_state = after,
|
||||
});
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status RecordingCommandContext::copy_texture(
|
||||
ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
@@ -754,6 +778,8 @@ const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) no
|
||||
return "upload_texture";
|
||||
case RecordedRenderCommandKind::generate_mipmaps:
|
||||
return "generate_mipmaps";
|
||||
case RecordedRenderCommandKind::transition_texture:
|
||||
return "transition_texture";
|
||||
case RecordedRenderCommandKind::copy_texture:
|
||||
return "copy_texture";
|
||||
case RecordedRenderCommandKind::read_texture:
|
||||
|
||||
@@ -21,6 +21,7 @@ enum class RecordedRenderCommandKind : std::uint8_t {
|
||||
draw,
|
||||
upload_texture,
|
||||
generate_mipmaps,
|
||||
transition_texture,
|
||||
copy_texture,
|
||||
read_texture,
|
||||
capture_frame,
|
||||
@@ -52,6 +53,8 @@ struct RecordedRenderCommand {
|
||||
std::uint32_t sampler_slot = 0;
|
||||
TextureDesc source_desc {};
|
||||
TextureDesc destination_desc {};
|
||||
TextureState before_state = TextureState::undefined;
|
||||
TextureState after_state = TextureState::undefined;
|
||||
ReadbackRegion readback_region {};
|
||||
ReadbackRegion source_region {};
|
||||
ReadbackRegion destination_region {};
|
||||
@@ -148,6 +151,10 @@ public:
|
||||
std::span<const std::byte> rgba_or_channel_bytes) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status generate_mipmaps(
|
||||
ITexture2D& texture) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status transition_texture(
|
||||
ITexture2D& texture,
|
||||
TextureState before,
|
||||
TextureState after) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status copy_texture(
|
||||
ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
|
||||
@@ -692,6 +692,78 @@ pp::foundation::Status validate_mipmap_generation_desc(TextureDesc desc) noexcep
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status validate_texture_state(TextureState state) noexcept
|
||||
{
|
||||
switch (state) {
|
||||
case TextureState::undefined:
|
||||
case TextureState::shader_read:
|
||||
case TextureState::render_target:
|
||||
case TextureState::upload_destination:
|
||||
case TextureState::copy_source:
|
||||
case TextureState::copy_destination:
|
||||
case TextureState::readback_source:
|
||||
case TextureState::present:
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
return pp::foundation::Status::invalid_argument("texture state is not supported");
|
||||
}
|
||||
|
||||
pp::foundation::Status validate_texture_transition_desc(
|
||||
TextureDesc desc,
|
||||
TextureState before,
|
||||
TextureState after) noexcept
|
||||
{
|
||||
const auto desc_status = validate_texture_desc(desc);
|
||||
if (!desc_status.ok()) {
|
||||
return desc_status;
|
||||
}
|
||||
|
||||
const auto before_status = validate_texture_state(before);
|
||||
if (!before_status.ok()) {
|
||||
return before_status;
|
||||
}
|
||||
|
||||
const auto after_status = validate_texture_state(after);
|
||||
if (!after_status.ok()) {
|
||||
return after_status;
|
||||
}
|
||||
|
||||
if (before == after) {
|
||||
return pp::foundation::Status::invalid_argument("texture transition must change state");
|
||||
}
|
||||
|
||||
if (after == TextureState::undefined) {
|
||||
return pp::foundation::Status::invalid_argument("texture transition destination must not be undefined");
|
||||
}
|
||||
|
||||
if (after == TextureState::shader_read && !has_texture_usage(desc.usage, TextureUsage::sampled)) {
|
||||
return pp::foundation::Status::invalid_argument("shader-read transition requires sampled usage");
|
||||
}
|
||||
|
||||
if (after == TextureState::render_target && !has_texture_usage(desc.usage, TextureUsage::render_target)) {
|
||||
return pp::foundation::Status::invalid_argument("render-target transition requires render_target usage");
|
||||
}
|
||||
|
||||
if (after == TextureState::upload_destination && !has_texture_usage(desc.usage, TextureUsage::upload_destination)) {
|
||||
return pp::foundation::Status::invalid_argument("upload transition requires upload_destination usage");
|
||||
}
|
||||
|
||||
if (after == TextureState::copy_source && !has_texture_usage(desc.usage, TextureUsage::copy_source)) {
|
||||
return pp::foundation::Status::invalid_argument("copy-source transition requires copy_source usage");
|
||||
}
|
||||
|
||||
if (after == TextureState::copy_destination && !has_texture_usage(desc.usage, TextureUsage::copy_destination)) {
|
||||
return pp::foundation::Status::invalid_argument("copy-destination transition requires copy_destination usage");
|
||||
}
|
||||
|
||||
if (after == TextureState::readback_source && !has_texture_usage(desc.usage, TextureUsage::readback_source)) {
|
||||
return pp::foundation::Status::invalid_argument("readback transition requires readback_source usage");
|
||||
}
|
||||
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status validate_blit_filter(BlitFilter filter) noexcept
|
||||
{
|
||||
switch (filter) {
|
||||
@@ -749,6 +821,30 @@ const char* texture_format_name(TextureFormat format) noexcept
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* texture_state_name(TextureState state) noexcept
|
||||
{
|
||||
switch (state) {
|
||||
case TextureState::undefined:
|
||||
return "undefined";
|
||||
case TextureState::shader_read:
|
||||
return "shader_read";
|
||||
case TextureState::render_target:
|
||||
return "render_target";
|
||||
case TextureState::upload_destination:
|
||||
return "upload_destination";
|
||||
case TextureState::copy_source:
|
||||
return "copy_source";
|
||||
case TextureState::copy_destination:
|
||||
return "copy_destination";
|
||||
case TextureState::readback_source:
|
||||
return "readback_source";
|
||||
case TextureState::present:
|
||||
return "present";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* primitive_topology_name(PrimitiveTopology topology) noexcept
|
||||
{
|
||||
switch (topology) {
|
||||
|
||||
@@ -35,6 +35,17 @@ enum class TextureUsage : std::uint32_t {
|
||||
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>(
|
||||
@@ -285,6 +296,10 @@ public:
|
||||
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,
|
||||
@@ -358,11 +373,17 @@ public:
|
||||
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]] 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* blend_factor_name(BlendFactor factor) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user