Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/test/test_apps/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ target_include_directories(gfxrecon-testapp-base
set(GFXRECON_ANDROID_TEST_APPS_DIR ${CMAKE_SOURCE_DIR}/..)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/util util)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/plugin plugin)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/schema schema)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/decode decode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/graphics graphics)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/format format)
Expand Down
1 change: 1 addition & 0 deletions android/tools/multi-win-replay/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/util util)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/plugin plugin)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/graphics graphics)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/format format)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/schema schema)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/decode decode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/encode encode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/android/framework/application-multi-win application-multi-win)
Expand Down
1 change: 1 addition & 0 deletions android/tools/quest_replay/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/util util)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/plugin plugin)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/graphics graphics)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/format format)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/schema schema)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/decode decode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/encode encode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/application application)
Expand Down
1 change: 1 addition & 0 deletions android/tools/replay/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/util util)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/plugin plugin)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/graphics graphics)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/format format)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/schema schema)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/decode decode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/encode encode)
add_subdirectory(${GFXRECON_SOURCE_DIR}/framework/application application)
Expand Down
8 changes: 8 additions & 0 deletions framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_subdirectory(plugin)
add_subdirectory(graphics)
add_subdirectory(format)
add_subdirectory(encode)
add_subdirectory(schema)
add_subdirectory(decode)
add_subdirectory(application)

Expand All @@ -12,9 +13,16 @@ if (${RUN_TESTS})
${CMAKE_CURRENT_LIST_DIR}/test/main.cpp
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${CMAKE_CURRENT_LIST_DIR}/test/test_arm_data_graph_structs.cpp>
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${CMAKE_CURRENT_LIST_DIR}/test/test_static_array_len.cpp>
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${CMAKE_CURRENT_LIST_DIR}/test/test_vulkan_schema.cpp>
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${CMAKE_CURRENT_LIST_DIR}/test/test_vulkan_pnext_encoder.cpp>
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${CMAKE_CURRENT_LIST_DIR}/test/schema_fill.h>
$<$<BOOL:${GFXRECON_ENABLE_VULKAN}>:${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_checks.cpp>
${CMAKE_CURRENT_LIST_DIR}/../tools/platform_debug_helper.cpp)
target_link_libraries(gfxrecon_framework_test PRIVATE gfxrecon_encode gfxrecon_decode)
if (MSVC)
# The schema tests instantiate per-structure templates over the whole catalog; the default COFF section
# limit is too small for them, as it is for gfxrecon_encode and gfxrecon_decode.
target_compile_options(gfxrecon_framework_test PRIVATE /bigobj)
# Force inclusion of "gfxrecon_disable_popup_result" variable in linking.
# On 32-bit windows, MSVC prefixes symbols with "_" but on 64-bit windows it doesn't.
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
Expand Down
13 changes: 13 additions & 0 deletions framework/decode/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ target_sources(gfxrecon_decode
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/annotation_handler.h
${CMAKE_CURRENT_LIST_DIR}/api_decoder.h
${CMAKE_CURRENT_LIST_DIR}/api_element_traits.h
${CMAKE_CURRENT_LIST_DIR}/api_payload.h
${CMAKE_CURRENT_LIST_DIR}/async_processor.h
${CMAKE_CURRENT_LIST_DIR}/async_processor.cpp
Expand Down Expand Up @@ -203,6 +204,9 @@ target_sources(gfxrecon_decode
$<$<BOOL:${D3D12_SUPPORT}>:${CMAKE_CURRENT_LIST_DIR}/dx12_pre_process_consumer.h>
$<$<BOOL:${D3D12_SUPPORT}>:${CMAKE_CURRENT_LIST_DIR}/dx12_dump_resources.h>
$<$<BOOL:${D3D12_SUPPORT}>:${CMAKE_CURRENT_LIST_DIR}/dx12_dump_resources.cpp>
${CMAKE_CURRENT_LIST_DIR}/vulkan_decode_action.h
${CMAKE_CURRENT_LIST_DIR}/vulkan_decode_struct.h
${CMAKE_CURRENT_LIST_DIR}/vulkan_decode_struct_impl.h
${CMAKE_CURRENT_LIST_DIR}/vulkan_decoder_base.h
${CMAKE_CURRENT_LIST_DIR}/vulkan_decoder_base.cpp
${CMAKE_CURRENT_LIST_DIR}/vulkan_default_allocator.h
Expand Down Expand Up @@ -317,6 +321,7 @@ target_sources(gfxrecon_decode
$<$<BOOL:${GFXRECON_TOCPP_SUPPORT}>:${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_cpp_consumer_extension.h>
$<$<BOOL:${GFXRECON_TOCPP_SUPPORT}>:${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_cpp_consumer_extension.cpp>
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_consumer.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_decode_api_element_traits.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_decoder_args.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_decoder.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_decoder.cpp
Expand All @@ -335,6 +340,13 @@ target_sources(gfxrecon_decode
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_replay_frame_loop_consumer_base.cpp
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_replay_dump_resources.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_replay_dump_resources.cpp
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_decoded_command_members.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_decoded_struct_members.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_fields.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_native_struct_members.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_types.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_schema_enumerants.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_struct_decoders_forward.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_struct_decoders.h
${GFXRECON_SOURCE_DIR}/framework/generated/generated_vulkan_struct_decoders.cpp
Expand Down Expand Up @@ -467,6 +479,7 @@ if (NOT ANDROID)
endif()

target_link_libraries(gfxrecon_decode
gfxrecon_schema
gfxrecon_graphics
gfxrecon_format
gfxrecon_util
Expand Down
103 changes: 103 additions & 0 deletions framework/decode/api_element_traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
** Copyright (c) 2026 LunarG, Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
** DEALINGS IN THE SOFTWARE.
*/

// The correspondence between an API element and its decoded representation.
//
// ApiElementTraits is keyed on the API element and says what decode uses to represent it. The other direction needs
// no trait: a decoded wrapper names its element as api_element, so an operation handed a wrapper reads it there. The
// namespace answers "traits for whom" -- these are what gfxrecon::decode knows about an API element, not everything
// that is known about it.
//
// Neither carries a schema, a Consumer interface, a Consumer member pointer, or compatibility invocation behavior. A
// decoded wrapper names no schema type of its own, so the wrapper stays usable as the graph's currency.
//
// The primary templates are API-agnostic, so each API's generated specializations are separate content, and this
// header pulls in the content for every enabled API. That is what makes it safe to include on its own. The concepts
// below are satisfied by a specialization, so a translation unit holding the declarations without the
// specializations would silently answer no rather than fail, and two such translation units would resolve the same
// constrained call to different functions. Including the content here removes that state rather than asking every
// caller to avoid it.

#ifndef GFXRECON_DECODE_API_ELEMENT_TRAITS_H
#define GFXRECON_DECODE_API_ELEMENT_TRAITS_H

#include "util/defines.h"

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(decode)

// Keyed on an API type descriptor or a command tag.
template <typename ApiElement>
struct ApiElementTraits;

template <typename ApiElement>
concept HasDecodedType = requires
{
typename ApiElementTraits<ApiElement>::decoded_type;
};

template <typename ApiElement>
concept HasDecodedValueType = requires
{
typename ApiElementTraits<ApiElement>::decoded_value_type;
};

// The concrete Decoded_Vk* and args:: declarations remain real types. This alias provides generic access without
// changing their type identity, linkage, or forward declarations.
template <typename ApiElement>
requires HasDecodedType<ApiElement>
using Decoded = typename ApiElementTraits<ApiElement>::decoded_type;

// A structure's decoded value type is its element type, which its API type descriptor already carries, so only a
// command declares one: a command's formal API-signature storage is not the element type of anything.
template <typename ApiElement>
requires HasDecodedValueType<ApiElement>
using DecodedValue = typename ApiElementTraits<ApiElement>::decoded_value_type;

// A decoded wrapper names the API element it represents, as api_element, the way it names its native type as
// struct_type. An operation handed a wrapper reaches the schema and the traits through that member, so no inverse
// trait is generated; the generated checks assert that each wrapper's element resolves back to the wrapper.
template <typename Wrapper>
concept HasApiElement = requires
{
typename Wrapper::api_element;
};

GFXRECON_END_NAMESPACE(decode)
GFXRECON_END_NAMESPACE(gfxrecon)

// THE ENTRY POINT. Include this rather than an API's generated traits header: both doors work, but one door is
// what keeps the specializations and the declarations from ever coming apart.
//
// Reaching the specializations means reaching every enabled API's type descriptors and every decoded wrapper and
// args declaration. That is inherent: the trait keys are the descriptors and the values are the wrappers. It does
// not reach a Field descriptor or a Schema: those live in separate generated files that only an Action's member
// traits and the field walk include, so naming Decoded<> here costs the wrappers, which any decode header already
// pays for, and not the schema.
//
// Each generated header includes this one back; the include guard makes that a no-op, and the primary templates
// above are declared before this point, so either include order works.
#if defined(GFXRECON_ENABLE_VULKAN)
#include "generated/generated_vulkan_decode_api_element_traits.h"
#endif

#endif // GFXRECON_DECODE_API_ELEMENT_TRAITS_H
2 changes: 1 addition & 1 deletion framework/decode/custom_openxr_struct_decoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "decode/struct_pointer_decoder.h"
#include "decode/openxr_next_node.h"
#include "generated/generated_openxr_struct_decoders_forward.h"
#include "generated/generated_vulkan_struct_decoders_forward.h"
#include "decode/vulkan_decode_struct.h"
#include "util/defines.h"

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
Expand Down
2 changes: 1 addition & 1 deletion framework/decode/custom_vulkan_struct_decoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "decode/string_decoder.h"
#include "decode/struct_pointer_decoder.h"
#include "decode/vulkan_pnext_node.h"
#include "generated/generated_vulkan_struct_decoders_forward.h"
#include "decode/vulkan_decode_struct.h"

#include "vulkan/vulkan.h"

Expand Down
8 changes: 8 additions & 0 deletions framework/decode/custom_vulkan_struct_to_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,5 +667,13 @@ void FieldToJson(nlohmann::ordered_json& jdata, const Decoded_VkDataGraphPipelin
}
}

void FieldToJson(nlohmann::ordered_json& jdata, const TypedStructDecoder* data)
{
// The one caller is generated and passes the address of an args member.
GFXRECON_ASSERT(data != nullptr);

FieldToJson(jdata, data->GetPNextNode());
}

GFXRECON_END_NAMESPACE(decode)
GFXRECON_END_NAMESPACE(gfxrecon)
5 changes: 5 additions & 0 deletions framework/decode/custom_vulkan_struct_to_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define GFXRECON_DECODE_CUSTOM_VULKAN_STRUCT_TO_JSON_H

#include "decode/custom_vulkan_struct_decoders.h"
#include "decode/vulkan_decode_typed_struct.h"
#include "generated/generated_vulkan_enum_to_json.h"
#include "generated/generated_vulkan_struct_to_json.h"
#include "generated/generated_vulkan_struct_decoders.h"
Expand Down Expand Up @@ -112,6 +113,10 @@ void FieldToJson(nlohmann::ordered_json& jdata, const std::vector<T>& data)

void FieldToJson(nlohmann::ordered_json& jdata, const Decoded_VkLayerSettingEXT* data);

// A command parameter declared VkBaseOutStructure*. Emits the concrete structure, selected by its sType, or nothing
// when the decoder holds none.
void FieldToJson(nlohmann::ordered_json& jdata, const TypedStructDecoder* data);

GFXRECON_END_NAMESPACE(decode)
GFXRECON_END_NAMESPACE(gfxrecon)

Expand Down
2 changes: 1 addition & 1 deletion framework/decode/descriptor_update_template_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "decode/custom_vulkan_struct_decoders_forward.h"
#include "decode/pointer_decoder_base.h"
#include "format/format.h"
#include "generated/generated_vulkan_struct_decoders_forward.h"
#include "decode/vulkan_decode_struct.h"
#include "util/defines.h"

#include <memory>
Expand Down
20 changes: 20 additions & 0 deletions framework/decode/pointer_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ class PointerDecoder : public PointerDecoderBase
size_t DecodeLUID(const uint8_t* buffer, size_t buffer_size) { return DecodeFrom<int64_t>(buffer, buffer_size); }
// clang-format on

// Decode a run recorded as one logical kind. Each named entry point above fixes a wire type and adds nothing
// else, which states a second time what format's kind tags already say; a caller holding a kind says it here
// and the width follows from the kind. Reaches kinds no named entry point covers -- there is no DecodeFlags64,
// and Decode<format::kind::Flags64> needs none.
template <format::HasEncodeType Kind>
size_t Decode(const uint8_t* buffer, size_t buffer_size)
{
return DecodeFrom<format::EncodeTypeFor<Kind>>(buffer, buffer_size);
}

private:
template <typename SrcT>
size_t DecodeFrom(const uint8_t* buffer, size_t buffer_size)
Expand Down Expand Up @@ -297,6 +307,16 @@ class PointerDecoder<T*> : public PointerDecoderBase
size_t DecodeSizeT(const uint8_t* buffer, size_t buffer_size) { return DecodeFrom<format::SizeTEncodeType>(buffer, buffer_size); }
// clang-format on

// Decode a run recorded as one logical kind. Each named entry point above fixes a wire type and adds nothing
// else, which states a second time what format's kind tags already say; a caller holding a kind says it here
// and the width follows from the kind. Reaches kinds no named entry point covers -- there is no DecodeFlags64,
// and Decode<format::kind::Flags64> needs none.
template <format::HasEncodeType Kind>
size_t Decode(const uint8_t* buffer, size_t buffer_size)
{
return DecodeFrom<format::EncodeTypeFor<Kind>>(buffer, buffer_size);
}

private:
template <typename SrcT>
size_t DecodeFrom(const uint8_t* buffer, size_t buffer_size)
Expand Down
2 changes: 1 addition & 1 deletion framework/decode/struct_pointer_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "decode/decode_allocator.h"
#include "decode/value_decoder.h"
#include "format/format.h"
#include "generated/generated_vulkan_struct_decoders_forward.h"
#include "decode/vulkan_decode_struct.h"
#include "util/defines.h"

#if defined(D3D12_SUPPORT)
Expand Down
7 changes: 7 additions & 0 deletions framework/decode/value_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ class ValueDecoder
return DecodeArray(buffer, buffer_size, arr, len);
}

// Decode a value recorded as one logical kind. See the note on PointerDecoder<T>::Decode.
template <format::HasEncodeType Kind, typename DstT>
static size_t Decode(const uint8_t* buffer, size_t buffer_size, DstT* value)
{
return DecodeValueFrom<format::EncodeTypeFor<Kind>>(buffer, buffer_size, value);
}

private:
template <typename DstT, typename SrcT>
static typename std::enable_if<!std::is_pointer<SrcT>::value && !std::is_pointer<DstT>::value, DstT>::type
Expand Down
Loading
Loading