* IN THE SOFTWARE.
*/
+#include <dlfcn.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include "radv_private.h"
#include "util/strtod.h"
+#include <xf86drm.h>
#include <amdgpu.h>
#include <amdgpu_drm.h>
#include "amdgpu_id.h"
#include "ac_llvm_util.h"
#include "vk_format.h"
#include "sid.h"
-#include "radv_timestamp.h"
#include "util/debug.h"
struct radv_dispatch_table dtable;
-struct radv_fence {
- struct radeon_winsys_fence *fence;
- bool submitted;
- bool signalled;
-};
+static int
+radv_get_function_timestamp(void *ptr, uint32_t* timestamp)
+{
+ Dl_info info;
+ struct stat st;
+ if (!dladdr(ptr, &info) || !info.dli_fname) {
+ return -1;
+ }
+ if (stat(info.dli_fname, &st)) {
+ return -1;
+ }
+ *timestamp = st.st_mtim.tv_sec;
+ return 0;
+}
+
+static int
+radv_device_get_cache_uuid(enum radeon_family family, void *uuid)
+{
+ uint32_t mesa_timestamp, llvm_timestamp;
+ uint16_t f = family;
+ memset(uuid, 0, VK_UUID_SIZE);
+ if (radv_get_function_timestamp(radv_device_get_cache_uuid, &mesa_timestamp) ||
+ radv_get_function_timestamp(LLVMInitializeAMDGPUTargetInfo, &llvm_timestamp))
+ return -1;
+
+ memcpy(uuid, &mesa_timestamp, 4);
+ memcpy((char*)uuid + 4, &llvm_timestamp, 4);
+ memcpy((char*)uuid + 8, &f, 2);
+ snprintf((char*)uuid + 10, VK_UUID_SIZE - 10, "radv");
+ return 0;
+}
static VkResult
radv_physical_device_init(struct radv_physical_device *device,
const char *path)
{
VkResult result;
+ drmVersionPtr version;
int fd;
fd = open(path, O_RDWR | O_CLOEXEC);
return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
"failed to open %s: %m", path);
+ version = drmGetVersion(fd);
+ if (!version) {
+ close(fd);
+ return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
+ "failed to get version %s: %m", path);
+ }
+
+ if (strcmp(version->name, "amdgpu")) {
+ drmFreeVersion(version);
+ close(fd);
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+ drmFreeVersion(version);
+
device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
device->instance = instance;
assert(strlen(path) < ARRAY_SIZE(device->path));
}
device->ws->query_info(device->ws, &device->rad_info);
result = radv_init_wsi(device);
- if (result != VK_SUCCESS)
+ if (result != VK_SUCCESS) {
+ device->ws->destroy(device->ws);
+ goto fail;
+ }
+
+ if (radv_device_get_cache_uuid(device->rad_info.family, device->uuid)) {
+ radv_finish_wsi(device);
+ device->ws->destroy(device->ws);
+ result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
+ "cannot generate UUID");
goto fail;
+ }
fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n");
device->name = device->rad_info.name;
+ close(fd);
return VK_SUCCESS;
fail:
#ifdef VK_USE_PLATFORM_XCB_KHR
{
.extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME,
- .specVersion = 5,
+ .specVersion = 6,
+ },
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ {
+ .extensionName = VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
+ .specVersion = 6,
},
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
{
.extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
- .specVersion = 4,
+ .specVersion = 5,
},
#endif
};
static const VkExtensionProperties device_extensions[] = {
+ {
+ .extensionName = VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
+ .specVersion = 1,
+ },
{
.extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- .specVersion = 67,
+ .specVersion = 68,
+ },
+ {
+ .extensionName = VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME,
+ .specVersion = 1,
+ },
+ {
+ .extensionName = VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME,
+ .specVersion = 1,
},
};
return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
}
- instance = radv_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
+ instance = vk_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (!instance)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
_mesa_locale_fini();
- radv_free(&instance->alloc, instance);
+ vk_free(&instance->alloc, instance);
}
VkResult radv_EnumeratePhysicalDevices(
} else if (*pPhysicalDeviceCount >= 1) {
pPhysicalDevices[0] = radv_physical_device_to_handle(&instance->physicalDevice);
*pPhysicalDeviceCount = 1;
+ } else if (*pPhysicalDeviceCount < instance->physicalDeviceCount) {
+ return VK_INCOMPLETE;
} else {
*pPhysicalDeviceCount = 0;
}
.largePoints = true,
.alphaToOne = true,
.multiViewport = false,
- .samplerAnisotropy = false, /* FINISHME */
+ .samplerAnisotropy = true,
.textureCompressionETC2 = false,
.textureCompressionASTC_LDR = false,
.textureCompressionBC = true,
};
}
-void
-radv_device_get_cache_uuid(void *uuid)
-{
- memset(uuid, 0, VK_UUID_SIZE);
- snprintf(uuid, VK_UUID_SIZE, "radv-%s", RADV_TIMESTAMP);
-}
-
void radv_GetPhysicalDeviceProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties)
.maxGeometryTotalOutputComponents = 1024,
.maxFragmentInputComponents = 128,
.maxFragmentOutputAttachments = 8,
- .maxFragmentDualSrcAttachments = 2,
+ .maxFragmentDualSrcAttachments = 1,
.maxFragmentCombinedOutputResources = 8,
.maxComputeSharedMemorySize = 32768,
.maxComputeWorkGroupCount = { 65535, 65535, 65535 },
};
strcpy(pProperties->deviceName, pdevice->name);
- radv_device_get_cache_uuid(pProperties->pipelineCacheUUID);
+ memcpy(pProperties->pipelineCacheUUID, pdevice->uuid, VK_UUID_SIZE);
}
void radv_GetPhysicalDeviceQueueFamilyProperties(
{
RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
- pMemoryProperties->memoryTypeCount = 3;
+ pMemoryProperties->memoryTypeCount = 4;
pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
.propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.heapIndex = 0,
};
pMemoryProperties->memoryTypes[1] = (VkMemoryType) {
+ .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ .heapIndex = 2,
+ };
+ pMemoryProperties->memoryTypes[2] = (VkMemoryType) {
.propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
- .heapIndex = 0,
+ .heapIndex = 1,
};
- pMemoryProperties->memoryTypes[2] = (VkMemoryType) {
- .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|
+ pMemoryProperties->memoryTypes[3] = (VkMemoryType) {
+ .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
- .heapIndex = 1,
+ .heapIndex = 2,
};
- pMemoryProperties->memoryHeapCount = 2;
+ pMemoryProperties->memoryHeapCount = 3;
pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
- .size = physical_device->rad_info.vram_size,
+ .size = physical_device->rad_info.vram_size -
+ physical_device->rad_info.visible_vram_size,
.flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
};
pMemoryProperties->memoryHeaps[1] = (VkMemoryHeap) {
+ .size = physical_device->rad_info.visible_vram_size,
+ .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+ };
+ pMemoryProperties->memoryHeaps[2] = (VkMemoryHeap) {
.size = physical_device->rad_info.gart_size,
.flags = 0,
};
}
-static VkResult
+static void
radv_queue_init(struct radv_device *device, struct radv_queue *queue)
{
queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
queue->device = device;
-
- return VK_SUCCESS;
}
static void
return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
}
- device = radv_alloc2(&physical_device->instance->alloc, pAllocator,
+ device = vk_alloc2(&physical_device->instance->alloc, pAllocator,
sizeof(*device), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (!device)
}
device->allow_fast_clears = env_var_as_boolean("RADV_FAST_CLEARS", false);
device->allow_dcc = !env_var_as_boolean("RADV_DCC_DISABLE", false);
+ device->shader_stats_dump = env_var_as_boolean("RADV_SHADER_STATS", false);
if (device->allow_fast_clears && device->allow_dcc)
radv_finishme("DCC fast clears have not been tested\n");
*pDevice = radv_device_to_handle(device);
return VK_SUCCESS;
fail_free:
- radv_free(&device->alloc, device);
+ vk_free(&device->alloc, device);
return result;
}
radv_queue_finish(&device->queue);
radv_device_finish_meta(device);
- radv_free(&device->alloc, device);
+ vk_free(&device->alloc, device);
}
VkResult radv_EnumerateInstanceExtensionProperties(
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties)
{
- unsigned i;
if (pProperties == NULL) {
*pPropertyCount = ARRAY_SIZE(global_extensions);
return VK_SUCCESS;
}
- for (i = 0; i < *pPropertyCount; i++)
- memcpy(&pProperties[i], &global_extensions[i], sizeof(VkExtensionProperties));
+ *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(global_extensions));
+ typed_memcpy(pProperties, global_extensions, *pPropertyCount);
- *pPropertyCount = i;
- if (i < ARRAY_SIZE(global_extensions))
+ if (*pPropertyCount < ARRAY_SIZE(global_extensions))
return VK_INCOMPLETE;
return VK_SUCCESS;
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties)
{
- unsigned i;
-
if (pProperties == NULL) {
*pPropertyCount = ARRAY_SIZE(device_extensions);
return VK_SUCCESS;
}
- for (i = 0; i < *pPropertyCount; i++)
- memcpy(&pProperties[i], &device_extensions[i], sizeof(VkExtensionProperties));
+ *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(device_extensions));
+ typed_memcpy(pProperties, device_extensions, *pPropertyCount);
- *pPropertyCount = i;
- if (i < ARRAY_SIZE(device_extensions))
+ if (*pPropertyCount < ARRAY_SIZE(device_extensions))
return VK_INCOMPLETE;
+
return VK_SUCCESS;
}
return VK_SUCCESS;
}
- mem = radv_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
+ mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (mem == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
- if (pAllocateInfo->memoryTypeIndex == 2)
+ if (pAllocateInfo->memoryTypeIndex == 1 || pAllocateInfo->memoryTypeIndex == 3)
domain = RADEON_DOMAIN_GTT;
else
domain = RADEON_DOMAIN_VRAM;
flags |= RADEON_FLAG_NO_CPU_ACCESS;
else
flags |= RADEON_FLAG_CPU_ACCESS;
+
+ if (pAllocateInfo->memoryTypeIndex == 1)
+ flags |= RADEON_FLAG_GTT_WC;
+
mem->bo = device->ws->buffer_create(device->ws, alloc_size, 32768,
domain, flags);
return VK_SUCCESS;
fail:
- radv_free2(&device->alloc, pAllocator, mem);
+ vk_free2(&device->alloc, pAllocator, mem);
return result;
}
device->ws->buffer_destroy(mem->bo);
mem->bo = NULL;
- radv_free2(&device->alloc, pAllocator, mem);
+ vk_free2(&device->alloc, pAllocator, mem);
}
VkResult radv_MapMemory(
VkFence* pFence)
{
RADV_FROM_HANDLE(radv_device, device, _device);
- struct radv_fence *fence = radv_alloc2(&device->alloc, pAllocator,
+ struct radv_fence *fence = vk_alloc2(&device->alloc, pAllocator,
sizeof(*fence), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!fence)
return;
device->ws->destroy_fence(fence->fence);
- radv_free2(&device->alloc, pAllocator, fence);
+ vk_free2(&device->alloc, pAllocator, fence);
}
static uint64_t radv_get_absolute_timeout(uint64_t timeout)
RADV_FROM_HANDLE(radv_device, device, _device);
RADV_FROM_HANDLE(radv_fence, fence, _fence);
+ if (fence->signalled)
+ return VK_SUCCESS;
if (!fence->submitted)
return VK_NOT_READY;
VkEvent* pEvent)
{
RADV_FROM_HANDLE(radv_device, device, _device);
- struct radv_event *event = radv_alloc2(&device->alloc, pAllocator,
+ struct radv_event *event = vk_alloc2(&device->alloc, pAllocator,
sizeof(*event), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
RADEON_DOMAIN_GTT,
RADEON_FLAG_CPU_ACCESS);
if (!event->bo) {
- radv_free2(&device->alloc, pAllocator, event);
+ vk_free2(&device->alloc, pAllocator, event);
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
if (!event)
return;
device->ws->buffer_destroy(event->bo);
- radv_free2(&device->alloc, pAllocator, event);
+ vk_free2(&device->alloc, pAllocator, event);
}
VkResult radv_GetEventStatus(
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
- buffer = radv_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
+ buffer = vk_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (buffer == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
if (!buffer)
return;
- radv_free2(&device->alloc, pAllocator, buffer);
+ vk_free2(&device->alloc, pAllocator, buffer);
}
static inline unsigned
size_t size = sizeof(*framebuffer) +
sizeof(struct radv_attachment_info) * pCreateInfo->attachmentCount;
- framebuffer = radv_alloc2(&device->alloc, pAllocator, size, 8,
+ framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (framebuffer == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
if (!fb)
return;
- radv_free2(&device->alloc, pAllocator, fb);
+ vk_free2(&device->alloc, pAllocator, fb);
}
static unsigned radv_tex_wrap(VkSamplerAddressMode address_mode)
return 0;
}
+static unsigned
+radv_tex_aniso_filter(unsigned filter)
+{
+ if (filter < 2)
+ return 0;
+ if (filter < 4)
+ return 1;
+ if (filter < 8)
+ return 2;
+ if (filter < 16)
+ return 3;
+ return 4;
+}
+
static void
radv_init_sampler(struct radv_device *device,
struct radv_sampler *sampler,
const VkSamplerCreateInfo *pCreateInfo)
{
- uint32_t max_aniso = 0;
- uint32_t max_aniso_ratio = 0;//TODO
- bool is_vi;
- is_vi = (device->instance->physicalDevice.rad_info.chip_class >= VI);
+ uint32_t max_aniso = pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1.0 ?
+ (uint32_t) pCreateInfo->maxAnisotropy : 0;
+ uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso);
+ bool is_vi = (device->instance->physicalDevice.rad_info.chip_class >= VI);
sampler->state[0] = (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) |
S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) |
S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) |
S_008F30_DEPTH_COMPARE_FUNC(radv_tex_compare(pCreateInfo->compareOp)) |
S_008F30_FORCE_UNNORMALIZED(pCreateInfo->unnormalizedCoordinates ? 1 : 0) |
+ S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) |
+ S_008F30_ANISO_BIAS(max_aniso_ratio) |
S_008F30_DISABLE_CUBE_WRAP(0) |
S_008F30_COMPAT_MODE(is_vi));
sampler->state[1] = (S_008F34_MIN_LOD(S_FIXED(CLAMP(pCreateInfo->minLod, 0, 15), 8)) |
- S_008F34_MAX_LOD(S_FIXED(CLAMP(pCreateInfo->maxLod, 0, 15), 8)));
+ S_008F34_MAX_LOD(S_FIXED(CLAMP(pCreateInfo->maxLod, 0, 15), 8)) |
+ S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0));
sampler->state[2] = (S_008F38_LOD_BIAS(S_FIXED(CLAMP(pCreateInfo->mipLodBias, -16, 16), 8)) |
S_008F38_XY_MAG_FILTER(radv_tex_filter(pCreateInfo->magFilter, max_aniso)) |
S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) |
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
- sampler = radv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
+ sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!sampler)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
if (!sampler)
return;
- radv_free2(&device->alloc, pAllocator, sampler);
+ vk_free2(&device->alloc, pAllocator, sampler);
}