Quantcast
Jump to content

Samsung Invites Unity Devs to Take on US$185,000 ‘Tizen App Challenge’


Alex
 Share

Recommended Posts

Any developer who has designed a game with Unity that has reached more than 10,000 installs in the Google Play or Apple App Store may enter the challenge. Simply port the existing app to Tizen and start selling it in the Tizen Store. The first 50 apps can get US$3,000 each, and the entrant with the most popular app (attaining the highest number of Tizen Store installations) will win the grand prize of US$20,000.

 

Samsung Electronics has announced that the Tizen App Challenge for Unity developers will commence on August 18th, 2016 - prior to the launch of the Samsung Z2, a new smartphone running on the Tizen operating system. If you are a developer who has made a Unity-based game that has reached more than 10,000 installs, you're eligible to enter the challenge.

appchallenge_logo.png

 

The contest will run from August 18 to November 21, with a total amount of US$185,000 in prizes up for grabs. The first 50 apps can get US$3,000 each when the apps are started to be for sale in Tizen Store. Additionally, top prizes will be awarded to three participants whose games reach the highest number of downloads during the contest period, in the amount of US$20,000, $10,000 and $5,000, respectively.

 

prize_0825.jpg

 

The challenge consists of two steps. Contestants must complete both in order to register their app and secure a chance to win the prizes.

  • Step 1: You'll need to show that your game has been made with Unity and has reached at least 10,000 downloads in the Google Play or Apple App Store.
  • Once you complete Step 1, you'll receive a confirmation email from Samsung. Then you'll be able to port your app to Tizen and register it in the Tizen Store.
  • To complete Step 2, you must submit the unique Content ID you'll receive once you've registered your app in the Tizen Store.

 

For more information on the Tizen App Challenge, visit

http://unity3d.com/partners/samsung/tizen-challenge/

View the full article

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Similar Topics

    • By STF News
      View the full blog at its source
    • By STF News
      View the full blog at its source
    • By STF News
      Start Date Oct 26, 2021
      Location Online
      Counting down the days until the first online SDC. We're cooking up something new for SDC21 on October 26th.
      Stay tuned for more info and get a first look at the event here.
      #SDC21 #ShapeDesignCreate #Samsung
      View the full blog at its source
    • By STF News
      The Samsung Developers team works with many companies in the mobile and gaming ecosystems. We're excited to support our partner, Arm, as they bring timely and relevant content to developers looking to build games and high-performance experiences. This Vulkan Extensions series will help developers get the most out of the new and game-changing Vulkan extensions on Samsung mobile devices.
      In previous blogs, we have already explored two key Vulkan extension game changers that will be enabled by Android R. These are Descriptor Indexing and Buffer Device Address. In this blog, we explore the third and final game changer, which is 'Timeline Semaphores'.
      The introduction of timeline semaphores is a large improvement to the synchronization model of Vulkan and is a required feature in Vulkan 1.2. It solves some fundamental grievances with the existing synchronization APIs in Vulkan.
      The problems with VkFence and VkSemaphore
      In earlier Vulkan extensions, there are two distinct synchronization objects for dealing with CPU <-> GPU synchronization and GPU queue <-> GPU queue synchronization.
      The VkFence object only deals with GPU -> CPU synchronization. Due to the explicit nature of Vulkan, you must keep track of when the GPU completes the work you submit to it.
      vkQueueSubmit(queue, …, fence); The previous code is the way we would use a fence, and later this fence can be waited on. When the fence signals, we know it is safe to free resources, read back data written by GPU, and so on. Overall, the VkFence interface was never a real problem in practice, except that it feels strange to have two entirely different API objects which essentially do the same thing.
      VkSemaphore on the other hand has some quirks which makes it difficult to use properly in sophisticated applications. VkSemaphore by default is a binary semaphore. The fundamental problem with binary semaphores is that we can only wait for a semaphore once. After we have waited for it, it automatically becomes unsignaled again. This binary nature is very annoying to deal with when we use multiple queues. For example, consider a scenario where we perform some work in the graphics queue, and want to synchronize that work with two different compute queues. If we know this scenario is coming up, we will then have to allocate two VkSemaphore objects, signal both objects, and wait for each of them in the different compute queues. This works, but we might not have the knowledge up front that this scenario will play out. Often where we are dealing with multiple queues, we have to be somewhat conservative and signal semaphore objects we never end up waiting for. This leads to another problem …
      A signaled semaphore, which is never waited for, is basically a dead and useless semaphore and should be destroyed. We cannot reset a VkSemaphore object on the CPU, so we cannot ever signal it again if we want to recycle VkSemaphore objects. A workaround would be to wait for the semaphore on the GPU in a random queue just to unsignal it, but this feels like a gross hack. It could also potentially cause performance issues, as waiting for a semaphore is a full GPU memory barrier.
      Object bloat is another considerable pitfall of the existing APIs. For every synchronization point we need, we require a new object. All these objects must be managed, and their lifetimes must be considered. This creates a lot of annoying “bloat” for engines.
      The timeline – fixing object bloat – fixing multiple waits
      The first observation we can make of a Vulkan queue is that submissions should generally complete in-order. To signal a synchronization object in vkQueueSubmit, the GPU waits for all previously submitted work to the queue, which includes the signaling operation of previous synchronization objects. Rather than assigning one object per submission, we synchronize in terms of number of submissions. A plain uint64_t counter can be used for each queue. When a submission completes, the number is monotonically increased, usually by one each time. This counter is contained inside a single timeline semaphore object. Rather than waiting for a specific synchronization object which matches a particular submission, we could wait for a single object and specify “wait until graphics queue submission #157 completes.”
      We can wait for any value multiple times as we wish, so there is no binary semaphore problem. Essentially, for each VkQueue we can create a single timeline semaphore on startup and leave it alone (uint64_t will not overflow until the heat death of the sun, do not worry about it). This is extremely convenient and makes it so much easier to implement complicated dependency management schemes.
      Unifying VkFence and VkSemaphore
      Timeline semaphores can be used very effectively on CPU as well:
      VkSemaphoreWaitInfoKHR info = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR }; info.semaphoreCount = 1; info.pSemaphores = &semaphore; info.pValues = &value; vkWaitSemaphoresKHR(device, &info, timeout); This completely removes the need to use VkFence. Another advantage of this method is that multiple threads can wait for a timeline semaphore. With VkFence, only one thread could access a VkFence at any one time.
      A timeline semaphore can even be signaled from the CPU as well, although this feature feels somewhat niche. It allows use cases where you submit work to the GPU early, but then 'kick' the submission using vkSignalSemaphoreKHR. The accompanying sample demonstrates a particular scenario where this function might be useful:
      VkSemaphoreSignalInfoKHR info = { VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR }; info.semaphore = semaphore; info.value = value; vkSignalSemaphoreKHR(device, &info); Creating a timeline semaphore
      When creating a semaphore, you can specify the type of semaphore and give it an initial value:
      VkSemaphoreCreateInfo info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; VkSemaphoreTypeCreateInfoKHR type_info = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR }; type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE_KHR; type_info.initialValue = 0; info.pNext = &type_info; vkCreateSemaphore(device, &info, NULL, &semaphore);
      Signaling and waiting on timeline semaphores
      When submitting work with vkQueueSubmit, you can chain another struct which provides counter values when using timeline semaphores, for example:
      VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; submit.waitSemaphoreCount = 1; submit.pWaitSemaphores = &compute_queue_semaphore; submit.pWaitDstStageMask = &wait_stage; submit.commandBufferCount = 1; submit.pCommandBuffers = &cmd; submit.signalSemaphoreCount = 1; submit.pSignalSemaphores = &graphics_queue_semaphore; VkTimelineSemaphoreSubmitInfoKHR timeline = { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR }; timeline.waitSemaphoreValueCount = 1; timeline.pWaitSemaphoreValues = &wait_value; timeline.signalSemaphoreValueCount = 1; timeline.pSignalSemaphoreValues = &signal_value; submit.pNext = &timeline; signal_value++; // Generally, you bump the timeline value once per submission. vkQueueSubmit(queue, 1, &submit, VK_NULL_HANDLE); Out of order signal and wait
      A strong requirement of Vulkan binary semaphores is that signals must be submitted before a wait on a semaphore can be submitted. This makes it easy to guarantee that deadlocks do not occur on the GPU, but it is also somewhat inflexible. In an application with many Vulkan queues and a task-based architecture, it is reasonable to submit work that is somewhat out of order. However, this still uses synchronization objects to ensure the right ordering when executing on the GPU. With timeline semaphores, the application can agree on the timeline values to use ahead of time, then go ahead and build commands and submit out of order. The driver is responsible for figuring out the submission order required to make it work. However, the application gets more ways to shoot itself in the foot with this approach. This is because it is possible to create a deadlock with multiple queues where queue A waits for queue B, and queue B waits for queue A at the same time.
      Ease of porting
      It is no secret that timeline semaphores are inherited largely from D3D12’s fence objects. From a portability angle, timeline semaphores make it much easier to have compatibility across the APIs.
      Caveats
      As the specification stands right now, you cannot use timeline semaphores with swap chains. This is generally not a big problem as synchronization with the swap chain tends to be explicit operations renderers need to take care of.
      Another potential caveat to consider is that the timeline semaphore might not have a direct kernel equivalent on current platforms, which means some extra emulation to handle it, especially the out-of-order submission feature. As the timeline synchronization model becomes the de-facto standard, I expect platforms to get more native support for it.
      Conclusion
      All three key Vulkan extension game changers improve the overall development and gaming experience through improving graphics and enabling new gaming use cases. We hope that we gave you enough samples to get you started as you try out these new Vulkan extensions to help bring your games to life
      Follow Up
      Thanks to Hans-Kristian Arntzen and the team at Arm for bringing this great content to the Samsung Developers community. We hope you find this information about Vulkan extensions useful for developing your upcoming mobile games.
      The Samsung Developers site has many resources for developers looking to build for and integrate with Samsung devices and services. Stay in touch with the latest news by creating a free account or by subscribing to our monthly newsletter. Visit the Marketing Resources page for information on promoting and distributing your apps and games. Finally, our developer forum is an excellent way to stay up-to-date on all things related to the Galaxy ecosystem.
      View the full blog at its source
    • By STF News
      The Samsung Developers team works with many companies in the mobile and gaming ecosystems. We're excited to support our partner, Arm, as they bring timely and relevant content to developers looking to build games and high-performance experiences. This Vulkan Extensions series will help developers get the most out of the new and game-changing Vulkan extensions on Samsung mobile devices.
      Android R is enabling a host of useful Vulkan extensions for mobile, with three being key 'game changers'. These are set to improve the state of graphics APIs for modern applications, enabling new use cases and changing how developers can design graphics renderers going forward. You can expect to see these features across a variety of Android smartphones, such as the new Samsung Galaxy S21, and existing Samsung Galaxy S models like the Samsung Galaxy S20. The first blog explored the first game changer extension for Vulkan – ‘Descriptor Indexing'. This blog explores the second game changer extension – ‘Buffer Device Address.’
      VK_KHR_buffer_device_address
      VK_KHR_buffer_device_address is a monumental extension that adds a unique feature to Vulkan that none of the competing graphics APIs support.
      Pointer support is something that has always been limited in graphics APIs, for good reason. Pointers complicate a lot of things, especially for shader compilers. It is also near impossible to deal with plain pointers in legacy graphics APIs, which rely on implicit synchronization.
      There are two key aspects to buffer_device_address (BDA). First, it is possible to query a GPU virtual address from a VkBuffer. This is a plain uint64_t. This address can be written anywhere you like, in uniform buffers, push constants, or storage buffers, to name a few.
      The key aspect which makes this extension unique is that a SPIR-V shader can load an address from a buffer and treat it as a pointer to storage buffer memory immediately. Pointer casting, pointer arithmetic and all sorts of clever trickery can be done inside the shader. There are many use cases for this feature. Some are performance-related, and some are new use cases that have not been possible before.
      Getting the GPU virtual address (VA)
      There are some hoops to jump through here. First, when allocating VkDeviceMemory, we must flag that the memory supports BDA:
      VkMemoryAllocateInfo info = {…}; VkMemoryAllocateFlagsInfo flags = {…}; flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; vkAllocateMemory(device, &info, NULL, &memory); Similarly, when creating a VkBuffer, we add the VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR usage flag. Once we have created a buffer, we can query the VA:
      VkBufferDeviceAddressInfoKHR info = {…}; info.buffer = buffer; VkDeviceSize va = vkGetBufferDeviceAddressKHR(device, &info); From here, this 64-bit value can be placed in a buffer. You can of course offset this VA. Alignment is never an issue as shaders specify explicit alignment later.
      A note on debugging
      When using BDA, there are some extra features that drivers must support. Since a pointer does not necessarily exist when replaying an application capture in a debug tool, the driver must be able to guarantee that virtual addresses returned by the driver remain stable across runs. To that end, debug tools supply the expected VA and the driver allocates that VA range. Applications do not care that much about this, but it is important to note that even if you can use BDA, you might not be able to debug with it.
      typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { VkStructureType sType; void* pNext; VkBool32 bufferDeviceAddress; VkBool32 bufferDeviceAddressCaptureReplay; VkBool32 bufferDeviceAddressMultiDevice; } VkPhysicalDeviceBufferDeviceAddressFeatures; If bufferDeviceAddressCaptureReplay is supported, tools like RenderDoc can support BDA.
      Using a pointer in a shader
      In Vulkan GLSL, there is the GL_EXT_buffer_reference extension which allows us to declare a pointer type. A pointer like this can be placed in a buffer, or we can convert to and from integers:
      #version 450 #extension GL_EXT_buffer_reference : require #extension GL_EXT_buffer_reference_uvec2 : require layout(local_size_x = 64) in; // These define pointer types. layout(buffer_reference, std430, buffer_reference_align = 16) readonly buffer ReadVec4 { vec4 values[]; }; layout(buffer_reference, std430, buffer_reference_align = 16) writeonly buffer WriteVec4 { vec4 values[]; }; layout(buffer_reference, std430, buffer_reference_align = 4) readonly buffer UnalignedVec4 { vec4 value; }; layout(push_constant, std430) uniform Registers { ReadVec4 src; WriteVec4 dst; } registers; Placing raw pointers in push constants avoids all indirection for getting to a buffer. If the driver allows it, the pointers can be placed directly in GPU registers before the shader begins executing.
      Not all devices support 64-bit integers, but it is possible to cast uvec2 <-> pointer. Doing address computation like this is fine.
      uvec2 uadd_64_32(uvec2 addr, uint offset) { uint carry; addr.x = uaddCarry(addr.x, offset, carry); addr.y += carry; return addr; } void main() { uint index = gl_GlobalInvocationID.x; registers.dst.values[index] = registers.src.values[index]; uvec2 addr = uvec2(registers.src); addr = uadd_64_32(addr, 20 * index); Cast a uvec2 to address and load a vec4 from it. This address is aligned to 4 bytes.
      registers.dst.values[index + 1024] = UnalignedVec4(addr).value; } Pointer or offsets?
      Using raw pointers is not always the best idea. A natural use case you could consider for pointers is that you have tree structures or list structures in GPU memory. With pointers, you can jump around as much as you want, and even write new pointers to buffers. However, a pointer is 64-bit and a typical performance consideration is to use 32-bit offsets (or even 16-bit offsets) if possible. Using offsets is the way to go if you can guarantee that all buffers live inside a single VkBuffer. On the other hand, the pointer approach can access any VkBuffer at any time without having to use descriptors. Therein lies the key strength of BDA.
      Extreme hackery: physical pointer as specialization constants
      This is a life saver in certain situations where you are desperate to debug something without any available descriptor set.
      A black magic hack is to place a BDA inside a specialization constant. This allows for accessing a pointer without using any descriptors. Do note that this breaks all forms of pipeline caching and is only suitable for debug code. Do not ship this kind of code. Perform this dark sorcery at your own risk:
      #version 450 #extension GL_EXT_buffer_reference : require #extension GL_EXT_buffer_reference_uvec2 : require layout(local_size_x = 64) in; layout(constant_id = 0) const uint DEBUG_ADDR_LO = 0; layout(constant_id = 1) const uint DEBUG_ADDR_HI = 0; layout(buffer_reference, std430, buffer_reference_align = 4) buffer DebugCounter { uint value; }; void main() { DebugCounter counter = DebugCounter(uvec2(DEBUG_ADDR_LO, DEBUG_ADDR_HI)); atomicAdd(counter.value, 1u); } Emitting SPIR-V with buffer_device_address
      In SPIR-V, there are some things to note. BDA is an especially useful feature for layering other APIs due to its extreme flexibility in how we access memory. Therefore, generating BDA code yourself is a reasonable use case to assume as well.
      Enables BDA in shaders.
      _OpCapability PhysicalStorageBufferAddresses OpExtension "SPV_KHR_physical_storage_buffer"_ The memory model is PhysicalStorageBuffer64 and not logical anymore.
      _OpMemoryModel PhysicalStorageBuffer64 GLSL450_ The buffer reference types are declared basically just like SSBOs.
      _OpDecorate %_runtimearr_v4float ArrayStride 16 OpMemberDecorate %ReadVec4 0 NonWritable OpMemberDecorate %ReadVec4 0 Offset 0 OpDecorate %ReadVec4 Block OpDecorate %_runtimearr_v4float_0 ArrayStride 16 OpMemberDecorate %WriteVec4 0 NonReadable OpMemberDecorate %WriteVec4 0 Offset 0 OpDecorate %WriteVec4 Block OpMemberDecorate %UnalignedVec4 0 NonWritable OpMemberDecorate %UnalignedVec4 0 Offset 0 OpDecorate %UnalignedVec4 Block_ Declare a pointer to the blocks. PhysicalStorageBuffer is the storage class to use.
      OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_WriteVec4 PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_ReadVec4 = OpTypePointer PhysicalStorageBuffer %ReadVec4 %_ptr_PhysicalStorageBuffer_WriteVec4 = OpTypePointer PhysicalStorageBuffer %WriteVec4 %_ptr_PhysicalStorageBuffer_UnalignedVec4 = OpTypePointer PhysicalStorageBuffer %UnalignedVec4 Load a physical pointer from PushConstant.
      _%55 = OpAccessChain %_ptr_PushConstant__ptr_PhysicalStorageBuffer_WriteVec4 %registers %int_1 %56 = OpLoad %_ptr_PhysicalStorageBuffer_WriteVec4 %55_ Access chain into it.
      _%66 = OpAccessChain %_ptr_PhysicalStorageBuffer_v4float %56 %int_0 %40_ Aligned must be specified when dereferencing physical pointers. Pointers can have any arbitrary address and must be explicitly aligned, so the compiler knows what to do.
      OpStore %66 %65 Aligned 16 For pointers, SPIR-V can bitcast between integers and pointers seamlessly, for example:
      %61 = OpLoad %_ptr_PhysicalStorageBuffer_ReadVec4 %60 %70 = OpBitcast %v2uint %61 // Do math on %70 %86 = OpBitcast %_ptr_PhysicalStorageBuffer_UnalignedVec4 %some_address
      Conclusion
      We have already explored two key Vulkan extension game changers through this blog and the previous one. The third and final part of this game changer blog series will explore ‘Timeline Semaphores’ and how developers can use this new extension to improve the development experience and enhance their games.
      Follow Up
      Thanks to Hans-Kristian Arntzen and the team at Arm for bringing this great content to the Samsung Developers community. We hope you find this information about Vulkan extensions useful for developing your upcoming mobile games.
      The Samsung Developers site has many resources for developers looking to build for and integrate with Samsung devices and services. Stay in touch with the latest news by creating a free account or by subscribing to our monthly newsletter. Visit the Marketing Resources page for information on promoting and distributing your apps and games. Finally, our developer forum is an excellent way to stay up-to-date on all things related to the Galaxy ecosystem.
      View the full blog at its source
×
×
  • Create New...