Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
923aa288
Commit
923aa288
authored
Nov 08, 2022
by
Jacek Caban
Committed by
Alexandre Julliard
Nov 09, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winevulkan: Use generated thunks for VkPipelineCreationFeedback conversion.
parent
9ff9f818
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
25 additions
and
134 deletions
+25
-134
make_vulkan
dlls/winevulkan/make_vulkan
+0
-15
vulkan.c
dlls/winevulkan/vulkan.c
+0
-115
vulkan_thunks.c
dlls/winevulkan/vulkan_thunks.c
+0
-0
vulkan_thunks.h
dlls/winevulkan/vulkan_thunks.h
+25
-4
No files found.
dlls/winevulkan/make_vulkan
View file @
923aa288
...
@@ -202,8 +202,6 @@ FUNCTION_OVERRIDES = {
...
@@ -202,8 +202,6 @@ FUNCTION_OVERRIDES = {
# Device functions
# Device functions
"vkAllocateCommandBuffers"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkAllocateCommandBuffers"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkCreateCommandPool"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
,
"extra_param"
:
"client_ptr"
},
"vkCreateCommandPool"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
,
"extra_param"
:
"client_ptr"
},
"vkCreateComputePipelines"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
PRIVATE
},
"vkCreateGraphicsPipelines"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
PRIVATE
},
"vkDestroyCommandPool"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkDestroyCommandPool"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkDestroyDevice"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkDestroyDevice"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkFreeCommandBuffers"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
"vkFreeCommandBuffers"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
,
"loader_thunk"
:
ThunkType
.
PRIVATE
},
...
@@ -249,9 +247,6 @@ FUNCTION_OVERRIDES = {
...
@@ -249,9 +247,6 @@ FUNCTION_OVERRIDES = {
"vkGetDeviceGroupSurfacePresentModesKHR"
:
{
"dispatch"
:
True
,
"driver"
:
True
,
"thunk"
:
ThunkType
.
PUBLIC
},
"vkGetDeviceGroupSurfacePresentModesKHR"
:
{
"dispatch"
:
True
,
"driver"
:
True
,
"thunk"
:
ThunkType
.
PUBLIC
},
"vkGetPhysicalDevicePresentRectanglesKHR"
:
{
"dispatch"
:
True
,
"driver"
:
True
,
"thunk"
:
ThunkType
.
PUBLIC
},
"vkGetPhysicalDevicePresentRectanglesKHR"
:
{
"dispatch"
:
True
,
"driver"
:
True
,
"thunk"
:
ThunkType
.
PUBLIC
},
# VK_KHR_ray_tracing_pipeline
"vkCreateRayTracingPipelinesKHR"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
PRIVATE
},
# VK_EXT_calibrated_timestamps
# VK_EXT_calibrated_timestamps
"vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkGetCalibratedTimestampsEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkGetCalibratedTimestampsEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
...
@@ -263,9 +258,6 @@ FUNCTION_OVERRIDES = {
...
@@ -263,9 +258,6 @@ FUNCTION_OVERRIDES = {
# VK_EXT_debug_report
# VK_EXT_debug_report
"vkCreateDebugReportCallbackEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkCreateDebugReportCallbackEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkDestroyDebugReportCallbackEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
"vkDestroyDebugReportCallbackEXT"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
NONE
},
# VK_NV_ray_tracing
"vkCreateRayTracingPipelinesNV"
:
{
"dispatch"
:
True
,
"driver"
:
False
,
"thunk"
:
ThunkType
.
PRIVATE
},
}
}
STRUCT_CHAIN_CONVERSIONS
=
{
STRUCT_CHAIN_CONVERSIONS
=
{
...
@@ -1954,9 +1946,6 @@ class VkStruct(Sequence):
...
@@ -1954,9 +1946,6 @@ class VkStruct(Sequence):
# FIXME: needs pointer array support
# FIXME: needs pointer array support
if
self
.
name
==
"VkAccelerationStructureGeometryKHR"
:
if
self
.
name
==
"VkAccelerationStructureGeometryKHR"
:
return
False
return
False
# FIXME: get rid of private thunks conversion
if
self
.
name
==
"VkPipelineCreationFeedback"
:
return
False
# pFixedRateFlags field is missing const, but it doesn't need output conversion
# pFixedRateFlags field is missing const, but it doesn't need output conversion
if
direction
==
Direction
.
OUTPUT
and
self
.
name
==
"VkImageCompressionControlEXT"
:
if
direction
==
Direction
.
OUTPUT
and
self
.
name
==
"VkImageCompressionControlEXT"
:
...
@@ -2008,10 +1997,6 @@ class VkStruct(Sequence):
...
@@ -2008,10 +1997,6 @@ class VkStruct(Sequence):
return
False
return
False
def
needs_host_type
(
self
):
def
needs_host_type
(
self
):
# FIXME: get rid of private thunks conversion
if
self
.
name
==
"VkPipelineCreationFeedback"
:
return
False
for
m
in
self
.
members
:
for
m
in
self
.
members
:
if
self
.
name
==
m
.
type
:
if
self
.
name
==
m
.
type
:
continue
continue
...
...
dlls/winevulkan/vulkan.c
View file @
923aa288
...
@@ -1587,121 +1587,6 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance handle, VkDebugReportCallba
...
@@ -1587,121 +1587,6 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance handle, VkDebugReportCallba
free
(
object
);
free
(
object
);
}
}
static
void
fixup_pipeline_feedback
(
VkPipelineCreationFeedback
*
feedback
,
uint32_t
count
)
{
#if defined(USE_STRUCT_CONVERSION)
struct
host_pipeline_feedback
{
VkPipelineCreationFeedbackFlags
flags
;
uint64_t
duration
;
}
*
host_feedback
;
int64_t
i
;
host_feedback
=
(
void
*
)
feedback
;
for
(
i
=
count
-
1
;
i
>=
0
;
i
--
)
{
memmove
(
&
feedback
[
i
].
duration
,
&
host_feedback
[
i
].
duration
,
sizeof
(
uint64_t
));
feedback
[
i
].
flags
=
host_feedback
[
i
].
flags
;
}
#endif
}
static
void
fixup_pipeline_feedback_info
(
const
void
*
pipeline_info
)
{
VkPipelineCreationFeedbackCreateInfo
*
feedback
;
feedback
=
find_next_struct
(
pipeline_info
,
VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO
);
if
(
!
feedback
)
return
;
fixup_pipeline_feedback
(
feedback
->
pPipelineCreationFeedback
,
1
);
fixup_pipeline_feedback
(
feedback
->
pPipelineStageCreationFeedbacks
,
feedback
->
pipelineStageCreationFeedbackCount
);
}
VkResult
wine_vkCreateComputePipelines
(
VkDevice
handle
,
VkPipelineCache
pipeline_cache
,
uint32_t
count
,
const
VkComputePipelineCreateInfo_host
*
create_infos
,
const
VkAllocationCallbacks
*
allocator
,
VkPipeline
*
pipelines
)
{
struct
wine_device
*
device
=
wine_device_from_handle
(
handle
);
VkResult
res
;
uint32_t
i
;
if
(
allocator
)
FIXME
(
"Support for allocation callbacks not implemented yet
\n
"
);
res
=
device
->
funcs
.
p_vkCreateComputePipelines
(
device
->
device
,
pipeline_cache
,
count
,
create_infos
,
NULL
/* allocator */
,
pipelines
);
for
(
i
=
0
;
i
<
count
;
i
++
)
fixup_pipeline_feedback_info
(
&
create_infos
[
i
]);
return
res
;
}
VkResult
wine_vkCreateGraphicsPipelines
(
VkDevice
handle
,
VkPipelineCache
pipeline_cache
,
uint32_t
count
,
const
VkGraphicsPipelineCreateInfo_host
*
create_infos
,
const
VkAllocationCallbacks
*
allocator
,
VkPipeline
*
pipelines
)
{
struct
wine_device
*
device
=
wine_device_from_handle
(
handle
);
VkResult
res
;
uint32_t
i
;
if
(
allocator
)
FIXME
(
"Support for allocation callbacks not implemented yet
\n
"
);
res
=
device
->
funcs
.
p_vkCreateGraphicsPipelines
(
device
->
device
,
pipeline_cache
,
count
,
create_infos
,
NULL
/* allocator */
,
pipelines
);
for
(
i
=
0
;
i
<
count
;
i
++
)
fixup_pipeline_feedback_info
(
&
create_infos
[
i
]);
return
res
;
}
VkResult
wine_vkCreateRayTracingPipelinesKHR
(
VkDevice
handle
,
VkDeferredOperationKHR
deferred_operation
,
VkPipelineCache
pipeline_cache
,
uint32_t
count
,
const
VkRayTracingPipelineCreateInfoKHR_host
*
create_infos
,
const
VkAllocationCallbacks
*
allocator
,
VkPipeline
*
pipelines
)
{
struct
wine_device
*
device
=
wine_device_from_handle
(
handle
);
VkResult
res
;
uint32_t
i
;
if
(
allocator
)
FIXME
(
"Support for allocation callbacks not implemented yet
\n
"
);
res
=
device
->
funcs
.
p_vkCreateRayTracingPipelinesKHR
(
device
->
device
,
deferred_operation
,
pipeline_cache
,
count
,
create_infos
,
NULL
/* allocator */
,
pipelines
);
for
(
i
=
0
;
i
<
count
;
i
++
)
fixup_pipeline_feedback_info
(
&
create_infos
[
i
]);
return
res
;
}
VkResult
wine_vkCreateRayTracingPipelinesNV
(
VkDevice
handle
,
VkPipelineCache
pipeline_cache
,
uint32_t
count
,
const
VkRayTracingPipelineCreateInfoNV_host
*
create_infos
,
const
VkAllocationCallbacks
*
allocator
,
VkPipeline
*
pipelines
)
{
struct
wine_device
*
device
=
wine_device_from_handle
(
handle
);
VkResult
res
;
uint32_t
i
;
if
(
allocator
)
FIXME
(
"Support for allocation callbacks not implemented yet
\n
"
);
res
=
device
->
funcs
.
p_vkCreateRayTracingPipelinesNV
(
device
->
device
,
pipeline_cache
,
count
,
create_infos
,
NULL
/* allocator */
,
pipelines
);
for
(
i
=
0
;
i
<
count
;
i
++
)
fixup_pipeline_feedback_info
(
&
create_infos
[
i
]);
return
res
;
}
NTSTATUS
vk_is_available_instance_function
(
void
*
arg
)
NTSTATUS
vk_is_available_instance_function
(
void
*
arg
)
{
{
struct
is_available_instance_function_params
*
params
=
arg
;
struct
is_available_instance_function_params
*
params
=
arg
;
...
...
dlls/winevulkan/vulkan_thunks.c
View file @
923aa288
This diff is collapsed.
Click to expand it.
dlls/winevulkan/vulkan_thunks.h
View file @
923aa288
...
@@ -956,6 +956,17 @@ typedef VkBufferViewCreateInfo VkBufferViewCreateInfo_host;
...
@@ -956,6 +956,17 @@ typedef VkBufferViewCreateInfo VkBufferViewCreateInfo_host;
#endif
#endif
#if defined(USE_STRUCT_CONVERSION)
#if defined(USE_STRUCT_CONVERSION)
typedef
struct
VkPipelineCreationFeedback_host
{
VkPipelineCreationFeedbackFlags
flags
;
uint64_t
duration
;
}
VkPipelineCreationFeedback_host
;
typedef
VkPipelineCreationFeedback
VkPipelineCreationFeedbackEXT
;
#else
typedef
VkPipelineCreationFeedback
VkPipelineCreationFeedback_host
;
#endif
#if defined(USE_STRUCT_CONVERSION)
typedef
struct
VkShaderModuleValidationCacheCreateInfoEXT_host
typedef
struct
VkShaderModuleValidationCacheCreateInfoEXT_host
{
{
VkStructureType
sType
;
VkStructureType
sType
;
...
@@ -995,6 +1006,20 @@ typedef VkPipelineShaderStageCreateInfo VkPipelineShaderStageCreateInfo_host;
...
@@ -995,6 +1006,20 @@ typedef VkPipelineShaderStageCreateInfo VkPipelineShaderStageCreateInfo_host;
#endif
#endif
#if defined(USE_STRUCT_CONVERSION)
#if defined(USE_STRUCT_CONVERSION)
typedef
struct
VkPipelineCreationFeedbackCreateInfo_host
{
VkStructureType
sType
;
const
void
*
pNext
;
VkPipelineCreationFeedback_host
*
pPipelineCreationFeedback
;
uint32_t
pipelineStageCreationFeedbackCount
;
VkPipelineCreationFeedback_host
*
pPipelineStageCreationFeedbacks
;
}
VkPipelineCreationFeedbackCreateInfo_host
;
typedef
VkPipelineCreationFeedbackCreateInfo
VkPipelineCreationFeedbackCreateInfoEXT
;
#else
typedef
VkPipelineCreationFeedbackCreateInfo
VkPipelineCreationFeedbackCreateInfo_host
;
#endif
#if defined(USE_STRUCT_CONVERSION)
typedef
struct
VkSubpassShadingPipelineCreateInfoHUAWEI_host
typedef
struct
VkSubpassShadingPipelineCreateInfoHUAWEI_host
{
{
VkStructureType
sType
;
VkStructureType
sType
;
...
@@ -2398,14 +2423,10 @@ typedef VkCopyDescriptorSet VkCopyDescriptorSet_host;
...
@@ -2398,14 +2423,10 @@ typedef VkCopyDescriptorSet VkCopyDescriptorSet_host;
/* Functions for which we have custom implementations outside of the thunks. */
/* Functions for which we have custom implementations outside of the thunks. */
VkResult
wine_vkAllocateCommandBuffers
(
VkDevice
device
,
const
VkCommandBufferAllocateInfo_host
*
pAllocateInfo
,
VkCommandBuffer
*
pCommandBuffers
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkAllocateCommandBuffers
(
VkDevice
device
,
const
VkCommandBufferAllocateInfo_host
*
pAllocateInfo
,
VkCommandBuffer
*
pCommandBuffers
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateCommandPool
(
VkDevice
device
,
const
VkCommandPoolCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkCommandPool
*
pCommandPool
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateCommandPool
(
VkDevice
device
,
const
VkCommandPoolCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkCommandPool
*
pCommandPool
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateComputePipelines
(
VkDevice
device
,
VkPipelineCache
pipelineCache
,
uint32_t
createInfoCount
,
const
VkComputePipelineCreateInfo_host
*
pCreateInfos
,
const
VkAllocationCallbacks
*
pAllocator
,
VkPipeline
*
pPipelines
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDebugReportCallbackEXT
(
VkInstance
instance
,
const
VkDebugReportCallbackCreateInfoEXT
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDebugReportCallbackEXT
*
pCallback
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDebugReportCallbackEXT
(
VkInstance
instance
,
const
VkDebugReportCallbackCreateInfoEXT
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDebugReportCallbackEXT
*
pCallback
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDebugUtilsMessengerEXT
(
VkInstance
instance
,
const
VkDebugUtilsMessengerCreateInfoEXT
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDebugUtilsMessengerEXT
*
pMessenger
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDebugUtilsMessengerEXT
(
VkInstance
instance
,
const
VkDebugUtilsMessengerCreateInfoEXT
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDebugUtilsMessengerEXT
*
pMessenger
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDevice
(
VkPhysicalDevice
physicalDevice
,
const
VkDeviceCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDevice
*
pDevice
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateDevice
(
VkPhysicalDevice
physicalDevice
,
const
VkDeviceCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkDevice
*
pDevice
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateGraphicsPipelines
(
VkDevice
device
,
VkPipelineCache
pipelineCache
,
uint32_t
createInfoCount
,
const
VkGraphicsPipelineCreateInfo_host
*
pCreateInfos
,
const
VkAllocationCallbacks
*
pAllocator
,
VkPipeline
*
pPipelines
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateInstance
(
const
VkInstanceCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkInstance
*
pInstance
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateInstance
(
const
VkInstanceCreateInfo
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkInstance
*
pInstance
,
void
*
client_ptr
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateRayTracingPipelinesKHR
(
VkDevice
device
,
VkDeferredOperationKHR
deferredOperation
,
VkPipelineCache
pipelineCache
,
uint32_t
createInfoCount
,
const
VkRayTracingPipelineCreateInfoKHR_host
*
pCreateInfos
,
const
VkAllocationCallbacks
*
pAllocator
,
VkPipeline
*
pPipelines
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateRayTracingPipelinesNV
(
VkDevice
device
,
VkPipelineCache
pipelineCache
,
uint32_t
createInfoCount
,
const
VkRayTracingPipelineCreateInfoNV_host
*
pCreateInfos
,
const
VkAllocationCallbacks
*
pAllocator
,
VkPipeline
*
pPipelines
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateWin32SurfaceKHR
(
VkInstance
instance
,
const
VkWin32SurfaceCreateInfoKHR
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkSurfaceKHR
*
pSurface
)
DECLSPEC_HIDDEN
;
VkResult
wine_vkCreateWin32SurfaceKHR
(
VkInstance
instance
,
const
VkWin32SurfaceCreateInfoKHR
*
pCreateInfo
,
const
VkAllocationCallbacks
*
pAllocator
,
VkSurfaceKHR
*
pSurface
)
DECLSPEC_HIDDEN
;
void
wine_vkDestroyCommandPool
(
VkDevice
device
,
VkCommandPool
commandPool
,
const
VkAllocationCallbacks
*
pAllocator
)
DECLSPEC_HIDDEN
;
void
wine_vkDestroyCommandPool
(
VkDevice
device
,
VkCommandPool
commandPool
,
const
VkAllocationCallbacks
*
pAllocator
)
DECLSPEC_HIDDEN
;
void
wine_vkDestroyDebugReportCallbackEXT
(
VkInstance
instance
,
VkDebugReportCallbackEXT
callback
,
const
VkAllocationCallbacks
*
pAllocator
)
DECLSPEC_HIDDEN
;
void
wine_vkDestroyDebugReportCallbackEXT
(
VkInstance
instance
,
VkDebugReportCallbackEXT
callback
,
const
VkAllocationCallbacks
*
pAllocator
)
DECLSPEC_HIDDEN
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment