From ce8876074f353ef9c632fded39c084663804e7e6 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Tue, 26 Jul 2022 21:01:24 +0000 Subject: [PATCH] Move code around in prep for CacheKey -> Stream refactor Moves code around to simplify viewing the diff for Change If7594c4ff7117454c1ab3d0afaeee5653120add8 Bug: dawn:1480, dawn:1481 Change-Id: Iecfe4356b1a933a46741cec185008ca1d927c0a6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96903 Kokoro: Kokoro Reviewed-by: Loko Kung Reviewed-by: Corentin Wallez Commit-Queue: Austin Eng --- src/dawn/native/BUILD.gn | 2 +- src/dawn/native/CMakeLists.txt | 2 +- src/dawn/native/CacheKey.h | 149 +-------------------- src/dawn/native/stream/Stream.h | 181 ++++++++++++++++++++++++++ src/dawn/native/vulkan/CacheKeyVk.cpp | 106 +++++++++++++-- src/dawn/native/vulkan/CacheKeyVk.h | 100 -------------- 6 files changed, 279 insertions(+), 261 deletions(-) create mode 100644 src/dawn/native/stream/Stream.h delete mode 100644 src/dawn/native/vulkan/CacheKeyVk.h diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index 07617ba87b..d8ddca2d00 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -334,6 +334,7 @@ source_set("sources") { "VertexFormat.cpp", "VertexFormat.h", "dawn_platform.h", + "stream/Stream.h", "utils/WGPUHelpers.cpp", "utils/WGPUHelpers.h", "webgpu_absl_format.cpp", @@ -604,7 +605,6 @@ source_set("sources") { "vulkan/BufferVk.cpp", "vulkan/BufferVk.h", "vulkan/CacheKeyVk.cpp", - "vulkan/CacheKeyVk.h", "vulkan/CommandBufferVk.cpp", "vulkan/CommandBufferVk.h", "vulkan/CommandRecordingContext.h", diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 7d88df1d9e..9306178361 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -193,6 +193,7 @@ target_sources(dawn_native PRIVATE "dawn_platform.h" "webgpu_absl_format.cpp" "webgpu_absl_format.h" + "stream/Stream.h" "utils/WGPUHelpers.cpp" "utils/WGPUHelpers.h" ) @@ -486,7 +487,6 @@ if (DAWN_ENABLE_VULKAN) "vulkan/BufferVk.cpp" "vulkan/BufferVk.h" "vulkan/CacheKeyVk.cpp" - "vulkan/CacheKeyVk.h" "vulkan/CommandBufferVk.cpp" "vulkan/CommandBufferVk.h" "vulkan/CommandRecordingContext.h" diff --git a/src/dawn/native/CacheKey.h b/src/dawn/native/CacheKey.h index b45c4c2119..786ae86c2a 100644 --- a/src/dawn/native/CacheKey.h +++ b/src/dawn/native/CacheKey.h @@ -111,151 +111,10 @@ CacheKey::UnsafeUnkeyedValue UnsafeUnkeyedValue(T&& value) { return CacheKey::UnsafeUnkeyedValue(std::forward(value)); } -// Specialized overload for CacheKey::UnsafeIgnoredValue which does nothing. -template -class CacheKeySerializer> { - public: - constexpr static void Serialize(CacheKey* key, const CacheKey::UnsafeUnkeyedValue&) {} -}; - -// Specialized overload for fundamental types. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T t) { - const char* it = reinterpret_cast(&t); - key->insert(key->end(), it, (it + sizeof(T))); - } -}; - -// Specialized overload for bitsets that are smaller than 64. -template -class CacheKeySerializer, std::enable_if_t<(N <= 64)>> { - public: - static void Serialize(CacheKey* key, const std::bitset& t) { key->Record(t.to_ullong()); } -}; - -// Specialized overload for bitsets since using the built-in to_ullong have a size limit. -template -class CacheKeySerializer, std::enable_if_t<(N > 64)>> { - public: - static void Serialize(CacheKey* key, const std::bitset& t) { - // Serializes the bitset into series of uint8_t, along with recording the size. - static_assert(N > 0); - key->Record(static_cast(N)); - uint8_t value = 0; - for (size_t i = 0; i < N; i++) { - value <<= 1; - // Explicitly convert to numeric since MSVC doesn't like mixing of bools. - value |= t[i] ? 1 : 0; - if (i % 8 == 7) { - // Whenever we fill an 8 bit value, record it and zero it out. - key->Record(value); - value = 0; - } - } - // Serialize the last value if we are not a multiple of 8. - if (N % 8 != 0) { - key->Record(value); - } - } -}; - -// Specialized overload for enums. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T t) { - CacheKeySerializer>::Serialize( - key, static_cast>(t)); - } -}; - -// Specialized overload for TypedInteger. -template -class CacheKeySerializer<::detail::TypedIntegerImpl> { - public: - static void Serialize(CacheKey* key, const ::detail::TypedIntegerImpl t) { - CacheKeySerializer::Serialize(key, static_cast(t)); - } -}; - -// Specialized overload for pointers. Since we are serializing for a cache key, we always -// serialize via value, not by pointer. To handle nullptr scenarios, we always serialize whether -// the pointer was nullptr followed by the contents if applicable. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T t) { - key->Record(t == nullptr); - if (t != nullptr) { - CacheKeySerializer>>::Serialize(key, *t); - } - } -}; - -// Specialized overload for fixed arrays of primitives. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T (&t)[N]) { - static_assert(N > 0); - key->Record(static_cast(N)); - const char* it = reinterpret_cast(t); - key->insert(key->end(), it, it + sizeof(t)); - } -}; - -// Specialized overload for fixed arrays of non-primitives. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T (&t)[N]) { - static_assert(N > 0); - key->Record(static_cast(N)); - for (size_t i = 0; i < N; i++) { - key->Record(t[i]); - } - } -}; - -// Specialized overload for CachedObjects. -template -class CacheKeySerializer>> { - public: - static void Serialize(CacheKey* key, const T& t) { key->Record(t.GetCacheKey()); } -}; - -// Specialized overload for std::vector. -template -class CacheKeySerializer> { - public: - static void Serialize(CacheKey* key, const std::vector& t) { key->RecordIterable(t); } -}; - -// Specialized overload for std::pair -template -class CacheKeySerializer> { - public: - static void Serialize(CacheKey* key, const std::pair& p) { - key->Record(p.first, p.second); - } -}; - -// Specialized overload for std::unordered_map -template -class CacheKeySerializer> { - public: - static void Serialize(CacheKey* key, const std::unordered_map& m) { - std::vector> ordered(m.begin(), m.end()); - std::sort(ordered.begin(), ordered.end(), - [](const std::pair& a, const std::pair& b) { - return std::less{}(a.first, b.first); - }); - key->RecordIterable(ordered); - } -}; - } // namespace dawn::native +// CacheKeySerializer implementation temporarily moved to stream/Stream.h to +// simplify the diff in the refactor to stream::Stream. +#include "dawn/native/stream/Stream.h" + #endif // SRC_DAWN_NATIVE_CACHEKEY_H_ diff --git a/src/dawn/native/stream/Stream.h b/src/dawn/native/stream/Stream.h new file mode 100644 index 0000000000..1797102568 --- /dev/null +++ b/src/dawn/native/stream/Stream.h @@ -0,0 +1,181 @@ +// Copyright 2022 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_STREAM_STREAM_H_ +#define SRC_DAWN_NATIVE_STREAM_STREAM_H_ + +#include +#include +#include +#include +#include +#include + +#include "dawn/common/Platform.h" +#include "dawn/common/TypedInteger.h" +#include "dawn/native/CacheKey.h" +#include "dawn/native/Error.h" + +namespace dawn::native { + +class CacheKey; + +// Specialized overload for CacheKey::UnsafeIgnoredValue which does nothing. +template +class CacheKeySerializer> { + public: + constexpr static void Serialize(CacheKey* key, const CacheKey::UnsafeUnkeyedValue&) {} +}; + +// Specialized overload for fundamental types. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T t) { + const char* it = reinterpret_cast(&t); + key->insert(key->end(), it, (it + sizeof(T))); + } +}; + +// Specialized overload for bitsets that are smaller than 64. +template +class CacheKeySerializer, std::enable_if_t<(N <= 64)>> { + public: + static void Serialize(CacheKey* key, const std::bitset& t) { key->Record(t.to_ullong()); } +}; + +// Specialized overload for bitsets since using the built-in to_ullong have a size limit. +template +class CacheKeySerializer, std::enable_if_t<(N > 64)>> { + public: + static void Serialize(CacheKey* key, const std::bitset& t) { + // Serializes the bitset into series of uint8_t, along with recording the size. + static_assert(N > 0); + key->Record(static_cast(N)); + uint8_t value = 0; + for (size_t i = 0; i < N; i++) { + value <<= 1; + // Explicitly convert to numeric since MSVC doesn't like mixing of bools. + value |= t[i] ? 1 : 0; + if (i % 8 == 7) { + // Whenever we fill an 8 bit value, record it and zero it out. + key->Record(value); + value = 0; + } + } + // Serialize the last value if we are not a multiple of 8. + if (N % 8 != 0) { + key->Record(value); + } + } +}; + +// Specialized overload for enums. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T t) { + CacheKeySerializer>::Serialize( + key, static_cast>(t)); + } +}; + +// Specialized overload for TypedInteger. +template +class CacheKeySerializer<::detail::TypedIntegerImpl> { + public: + static void Serialize(CacheKey* key, const ::detail::TypedIntegerImpl t) { + CacheKeySerializer::Serialize(key, static_cast(t)); + } +}; + +// Specialized overload for pointers. Since we are serializing for a cache key, we always +// serialize via value, not by pointer. To handle nullptr scenarios, we always serialize whether +// the pointer was nullptr followed by the contents if applicable. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T t) { + key->Record(t == nullptr); + if (t != nullptr) { + CacheKeySerializer>>::Serialize(key, *t); + } + } +}; + +// Specialized overload for fixed arrays of primitives. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T (&t)[N]) { + static_assert(N > 0); + key->Record(static_cast(N)); + const char* it = reinterpret_cast(t); + key->insert(key->end(), it, it + sizeof(t)); + } +}; + +// Specialized overload for fixed arrays of non-primitives. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T (&t)[N]) { + static_assert(N > 0); + key->Record(static_cast(N)); + for (size_t i = 0; i < N; i++) { + key->Record(t[i]); + } + } +}; + +// Specialized overload for CachedObjects. +template +class CacheKeySerializer>> { + public: + static void Serialize(CacheKey* key, const T& t) { key->Record(t.GetCacheKey()); } +}; + +// Specialized overload for std::vector. +template +class CacheKeySerializer> { + public: + static void Serialize(CacheKey* key, const std::vector& t) { key->RecordIterable(t); } +}; + +// Specialized overload for std::pair +template +class CacheKeySerializer> { + public: + static void Serialize(CacheKey* key, const std::pair& p) { + key->Record(p.first, p.second); + } +}; + +// Specialized overload for std::unordered_map +template +class CacheKeySerializer> { + public: + static void Serialize(CacheKey* key, const std::unordered_map& m) { + std::vector> ordered(m.begin(), m.end()); + std::sort(ordered.begin(), ordered.end(), + [](const std::pair& a, const std::pair& b) { + return std::less{}(a.first, b.first); + }); + key->RecordIterable(ordered); + } +}; + +} // namespace dawn::native + +#endif // SRC_DAWN_NATIVE_STREAM_STREAM_H_ diff --git a/src/dawn/native/vulkan/CacheKeyVk.cpp b/src/dawn/native/vulkan/CacheKeyVk.cpp index 3a8266783c..2b6d51b4b6 100644 --- a/src/dawn/native/vulkan/CacheKeyVk.cpp +++ b/src/dawn/native/vulkan/CacheKeyVk.cpp @@ -14,11 +14,89 @@ #include -#include "dawn/native/vulkan/CacheKeyVk.h" +#include "dawn/common/Assert.h" +#include "dawn/common/vulkan_platform.h" +#include "dawn/native/CacheKey.h" #include "dawn/native/vulkan/RenderPassCache.h" +#include "icd/generated/vk_typemap_helper.h" + namespace dawn::native { +namespace { + +namespace detail { + +template +void ValidatePnextImpl(const VkBaseOutStructure* root) { + const VkBaseOutStructure* next = reinterpret_cast(root->pNext); + while (next != nullptr) { + // Assert that the type of each pNext struct is exactly one of the specified + // templates. + ASSERT(((LvlTypeMap::kSType == next->sType ? 1 : 0) + ... + 0) == 1); + next = reinterpret_cast(next->pNext); + } +} + +template +void SerializePnextImpl(CacheKey* key, const VkBaseOutStructure* root) { + const VkBaseOutStructure* next = reinterpret_cast(root->pNext); + const VK_STRUCT_TYPE* found = nullptr; + while (next != nullptr) { + if (LvlTypeMap::kSType == next->sType) { + if (found == nullptr) { + found = reinterpret_cast(next); + } else { + // Fail an assert here since that means that the chain had more than one of + // the same typed chained object. + ASSERT(false); + } + } + next = reinterpret_cast(next->pNext); + } + if (found != nullptr) { + key->Record(found); + } +} + +template 0)>> +void SerializePnextImpl(CacheKey* key, const VkBaseOutStructure* root) { + SerializePnextImpl(key, root); + SerializePnextImpl(key, root); +} + +template +const VkBaseOutStructure* ToVkBaseOutStructure(const VK_STRUCT_TYPE* t) { + // Checks to ensure proper type safety. + static_assert(offsetof(VK_STRUCT_TYPE, sType) == offsetof(VkBaseOutStructure, sType) && + offsetof(VK_STRUCT_TYPE, pNext) == offsetof(VkBaseOutStructure, pNext), + "Argument type is not a proper Vulkan structure type"); + return reinterpret_cast(t); +} + +} // namespace detail + +template 0)>> +void SerializePnext(CacheKey* key, const VK_STRUCT_TYPE* t) { + const VkBaseOutStructure* root = detail::ToVkBaseOutStructure(t); + detail::ValidatePnextImpl(root); + detail::SerializePnextImpl(key, root); +} + +// Empty template specialization so that we can put this in to ensure failures occur if new +// extensions are added without updating serialization. +template +void SerializePnext(CacheKey* key, const VK_STRUCT_TYPE* t) { + const VkBaseOutStructure* root = detail::ToVkBaseOutStructure(t); + detail::ValidatePnextImpl<>(root); +} + +} // namespace + template <> void CacheKeySerializer::Serialize( CacheKey* key, @@ -31,7 +109,7 @@ void CacheKeySerializer::Serialize( CacheKey* key, const VkDescriptorSetLayoutCreateInfo& t) { key->Record(t.flags).RecordIterable(t.pBindings, t.bindingCount); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -47,7 +125,7 @@ void CacheKeySerializer::Serialize( // The set layouts are not serialized here because they are pointers to backend objects. // They need to be cross-referenced with the frontend objects and serialized from there. key->Record(t.flags).RecordIterable(t.pPushConstantRanges, t.pushConstantRangeCount); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -85,7 +163,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags, t.stage) .RecordIterable(t.pName, strlen(t.pName)) .Record(t.pSpecializationInfo); - vulkan::SerializePnext(key, &t); + SerializePnext(key, &t); } template <> @@ -121,7 +199,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags) .RecordIterable(t.pVertexBindingDescriptions, t.vertexBindingDescriptionCount) .RecordIterable(t.pVertexAttributeDescriptions, t.vertexAttributeDescriptionCount); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -129,7 +207,7 @@ void CacheKeySerializer::Serialize( CacheKey* key, const VkPipelineInputAssemblyStateCreateInfo& t) { key->Record(t.flags, t.topology, t.primitiveRestartEnable); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -137,7 +215,7 @@ void CacheKeySerializer::Serialize( CacheKey* key, const VkPipelineTessellationStateCreateInfo& t) { key->Record(t.flags, t.patchControlPoints); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -167,7 +245,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags) .RecordIterable(t.pViewports, t.viewportCount) .RecordIterable(t.pScissors, t.scissorCount); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -177,7 +255,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags, t.depthClampEnable, t.rasterizerDiscardEnable, t.polygonMode, t.cullMode, t.frontFace, t.depthBiasEnable, t.depthBiasConstantFactor, t.depthBiasClamp, t.depthBiasSlopeFactor, t.lineWidth); - vulkan::SerializePnext(key, &t); + SerializePnext(key, &t); } template <> @@ -186,7 +264,7 @@ void CacheKeySerializer::Serialize( const VkPipelineMultisampleStateCreateInfo& t) { key->Record(t.flags, t.rasterizationSamples, t.sampleShadingEnable, t.minSampleShading, t.pSampleMask, t.alphaToCoverageEnable, t.alphaToOneEnable); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -202,7 +280,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags, t.depthTestEnable, t.depthWriteEnable, t.depthCompareOp, t.depthBoundsTestEnable, t.stencilTestEnable, t.front, t.back, t.minDepthBounds, t.maxDepthBounds); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -220,7 +298,7 @@ void CacheKeySerializer::Serialize( key->Record(t.flags, t.logicOpEnable, t.logicOp) .RecordIterable(t.pAttachments, t.attachmentCount) .Record(t.blendConstants); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -228,7 +306,7 @@ void CacheKeySerializer::Serialize( CacheKey* key, const VkPipelineDynamicStateCreateInfo& t) { key->Record(t.flags).RecordIterable(t.pDynamicStates, t.dynamicStateCount); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } template <> @@ -266,7 +344,7 @@ void CacheKeySerializer::Serialize( .Record(t.pVertexInputState, t.pInputAssemblyState, t.pTessellationState, t.pViewportState, t.pRasterizationState, t.pMultisampleState, t.pDepthStencilState, t.pColorBlendState, t.pDynamicState, t.subpass); - vulkan::SerializePnext<>(key, &t); + SerializePnext(key, &t); } } // namespace dawn::native diff --git a/src/dawn/native/vulkan/CacheKeyVk.h b/src/dawn/native/vulkan/CacheKeyVk.h deleted file mode 100644 index 80b04dbd9a..0000000000 --- a/src/dawn/native/vulkan/CacheKeyVk.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2022 The Dawn Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SRC_DAWN_NATIVE_VULKAN_CACHEKEYVK_H_ -#define SRC_DAWN_NATIVE_VULKAN_CACHEKEYVK_H_ - -#include - -#include "dawn/common/Assert.h" -#include "dawn/common/vulkan_platform.h" -#include "dawn/native/CacheKey.h" - -#include "icd/generated/vk_typemap_helper.h" - -namespace dawn::native::vulkan { - -namespace detail { - -template -void ValidatePnextImpl(const VkBaseOutStructure* root) { - const VkBaseOutStructure* next = reinterpret_cast(root->pNext); - while (next != nullptr) { - // Assert that the type of each pNext struct is exactly one of the specified - // templates. - ASSERT(((LvlTypeMap::kSType == next->sType ? 1 : 0) + ... + 0) == 1); - next = reinterpret_cast(next->pNext); - } -} - -template -void SerializePnextImpl(CacheKey* key, const VkBaseOutStructure* root) { - const VkBaseOutStructure* next = reinterpret_cast(root->pNext); - const VK_STRUCT_TYPE* found = nullptr; - while (next != nullptr) { - if (LvlTypeMap::kSType == next->sType) { - if (found == nullptr) { - found = reinterpret_cast(next); - } else { - // Fail an assert here since that means that the chain had more than one of - // the same typed chained object. - ASSERT(false); - } - } - next = reinterpret_cast(next->pNext); - } - if (found != nullptr) { - key->Record(found); - } -} - -template 0)>> -void SerializePnextImpl(CacheKey* key, const VkBaseOutStructure* root) { - SerializePnextImpl(key, root); - SerializePnextImpl(key, root); -} - -template -const VkBaseOutStructure* ToVkBaseOutStructure(const VK_STRUCT_TYPE* t) { - // Checks to ensure proper type safety. - static_assert(offsetof(VK_STRUCT_TYPE, sType) == offsetof(VkBaseOutStructure, sType) && - offsetof(VK_STRUCT_TYPE, pNext) == offsetof(VkBaseOutStructure, pNext), - "Argument type is not a proper Vulkan structure type"); - return reinterpret_cast(t); -} - -} // namespace detail - -template 0)>> -void SerializePnext(CacheKey* key, const VK_STRUCT_TYPE* t) { - const VkBaseOutStructure* root = detail::ToVkBaseOutStructure(t); - detail::ValidatePnextImpl(root); - detail::SerializePnextImpl(key, root); -} - -// Empty template specialization so that we can put this in to ensure failures occur if new -// extensions are added without updating serialization. -template -void SerializePnext(CacheKey* key, const VK_STRUCT_TYPE* t) { - const VkBaseOutStructure* root = detail::ToVkBaseOutStructure(t); - detail::ValidatePnextImpl<>(root); -} - -} // namespace dawn::native::vulkan - -#endif // SRC_DAWN_NATIVE_VULKAN_CACHEKEYVK_H_