Skip to content
Draft
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
193 changes: 193 additions & 0 deletions entry/src/main/cpp/render/model_3d_sponza.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1567,3 +1567,196 @@ void VulkanExample::loadShadingRateImage()

LOGI("VulkanExample loadShadingRateImage: Successfully loaded shading rate image");
}

void VulkanExample::generate2x2ShadingRate()
{
LOGI("VulkanExample generate2x2ShadingRate: Generating 2x2 shading rate pattern");

// Only proceed if VRS is enabled and the image exists
if (!use_vrs || frameBuffers.shadingRate.color.image == VK_NULL_HANDLE) {
LOGI("VulkanExample generate2x2ShadingRate: VRS not enabled or image not available, skipping generation");
return;
}

// Get image info
VkImageSubresource subResource = {};
subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subResource.mipLevel = 0;
subResource.arrayLayer = 0;

VkSubresourceLayout subResourceLayout;
vkGetImageSubresourceLayout(device, frameBuffers.shadingRate.color.image, &subResource, &subResourceLayout);

// Map the image memory
void* data = nullptr;
VkResult result = vkMapMemory(device, frameBuffers.shadingRate.color.mem, 0, VK_WHOLE_SIZE, 0, &data);
if (result != VK_SUCCESS) {
LOGE("VulkanExample generate2x2ShadingRate: Failed to map memory, result: %{public}d", result);
return;
}

// Fill the entire shading rate image with 2x2 shading rate
// VK_FRAGMENT_SHADING_RATE_2X2_BIT_KHR = 5 (0x5)
uint8_t* imageData = (uint8_t*)data + subResourceLayout.offset;
uint32_t imageSize = frameBuffers.shadingRate.width * frameBuffers.shadingRate.height;

for (uint32_t i = 0; i < imageSize; i++) {
imageData[i] = 0x5; // 2x2 shading rate
}

vkUnmapMemory(device, frameBuffers.shadingRate.color.mem);

LOGI("VulkanExample generate2x2ShadingRate: Successfully generated 2x2 shading rate pattern");
}

void VulkanExample::save2x2ShadingRate()
{
LOGI("VulkanExample save2x2ShadingRate: Generating and saving 2x2 shading rate image");

// First generate the 2x2 pattern
generate2x2ShadingRate();

// Only proceed if VRS is enabled and the image exists
if (!use_vrs || frameBuffers.shadingRate.color.image == VK_NULL_HANDLE) {
LOGI("VulkanExample save2x2ShadingRate: VRS not enabled or image not available, skipping save");
return;
}

// Get image info
VkImageSubresource subResource = {};
subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subResource.mipLevel = 0;
subResource.arrayLayer = 0;

VkSubresourceLayout subResourceLayout;
vkGetImageSubresourceLayout(device, frameBuffers.shadingRate.color.image, &subResource, &subResourceLayout);

// Map the image memory
void* data = nullptr;
VkResult result = vkMapMemory(device, frameBuffers.shadingRate.color.mem, 0, VK_WHOLE_SIZE, 0, &data);
if (result != VK_SUCCESS) {
LOGE("VulkanExample save2x2ShadingRate: Failed to map memory, result: %{public}d", result);
return;
}

// Create file for saving
File file;
std::string filePath = "/data/storage/el2/base/haps/entry/cache/shading_rate_2x2.dat";
if (!file.Open(filePath, File::FILE_CREATE)) {
LOGE("VulkanExample save2x2ShadingRate: Failed to create file: %{public}s", filePath.c_str());
vkUnmapMemory(device, frameBuffers.shadingRate.color.mem);
return;
}

// Write image metadata
uint32_t width = frameBuffers.shadingRate.width;
uint32_t height = frameBuffers.shadingRate.height;
VkFormat format = frameBuffers.shadingRate.color.format;

if (file.Write(&width, sizeof(uint32_t)) != sizeof(uint32_t) ||
file.Write(&height, sizeof(uint32_t)) != sizeof(uint32_t) ||
file.Write(&format, sizeof(VkFormat)) != sizeof(VkFormat) ||
file.Write(&subResourceLayout.size, sizeof(VkDeviceSize)) != sizeof(VkDeviceSize)) {
LOGE("VulkanExample save2x2ShadingRate: Failed to write metadata");
file.Close();
vkUnmapMemory(device, frameBuffers.shadingRate.color.mem);
return;
}

// Write image data
char* imageData = (char*)data + subResourceLayout.offset;
if (file.Write(imageData, subResourceLayout.size) != subResourceLayout.size) {
LOGE("VulkanExample save2x2ShadingRate: Failed to write image data");
} else {
LOGI("VulkanExample save2x2ShadingRate: Successfully saved %{public}llu bytes", subResourceLayout.size);
}

file.Close();
vkUnmapMemory(device, frameBuffers.shadingRate.color.mem);

LOGI("VulkanExample save2x2ShadingRate: Successfully saved 2x2 shading rate image");
}

void VulkanExample::load2x2ShadingRate()
{
LOGI("VulkanExample load2x2ShadingRate: Loading 2x2 shading rate image from file");

std::string filePath = "/data/storage/el2/base/haps/entry/cache/shading_rate_2x2.dat";
if (!File::IsFileExist(filePath)) {
LOGI("VulkanExample load2x2ShadingRate: File does not exist, skipping load");
return;
}

// Only proceed if the image exists
if (frameBuffers.shadingRate.color.image == VK_NULL_HANDLE) {
LOGI("VulkanExample load2x2ShadingRate: Shading rate image not created yet, skipping load");
return;
}

File file;
if (!file.Open(filePath, File::FILE_READ)) {
LOGE("VulkanExample load2x2ShadingRate: Failed to open file: %{public}s", filePath.c_str());
return;
}

// Read metadata
uint32_t savedWidth, savedHeight;
VkFormat savedFormat;
VkDeviceSize savedSize;

if (file.Read(&savedWidth, sizeof(uint32_t)) != sizeof(uint32_t) ||
file.Read(&savedHeight, sizeof(uint32_t)) != sizeof(uint32_t) ||
file.Read(&savedFormat, sizeof(VkFormat)) != sizeof(VkFormat) ||
file.Read(&savedSize, sizeof(VkDeviceSize)) != sizeof(VkDeviceSize)) {
LOGE("VulkanExample load2x2ShadingRate: Failed to read metadata");
file.Close();
return;
}

// Verify compatibility
if (savedWidth != frameBuffers.shadingRate.width ||
savedHeight != frameBuffers.shadingRate.height ||
savedFormat != frameBuffers.shadingRate.color.format) {
LOGE("VulkanExample load2x2ShadingRate: Image format mismatch - saved: %{public}dx%{public}d fmt:%{public}d, current: %{public}dx%{public}d fmt:%{public}d",
savedWidth, savedHeight, savedFormat, frameBuffers.shadingRate.width, frameBuffers.shadingRate.height, frameBuffers.shadingRate.color.format);
file.Close();
return;
}

// Get current image layout info
VkImageSubresource subResource = {};
subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subResource.mipLevel = 0;
subResource.arrayLayer = 0;

VkSubresourceLayout subResourceLayout;
vkGetImageSubresourceLayout(device, frameBuffers.shadingRate.color.image, &subResource, &subResourceLayout);

if (savedSize != subResourceLayout.size) {
LOGE("VulkanExample load2x2ShadingRate: Size mismatch - saved: %{public}llu, current: %{public}llu", savedSize, subResourceLayout.size);
file.Close();
return;
}

// Map current image memory
void* data = nullptr;
VkResult result = vkMapMemory(device, frameBuffers.shadingRate.color.mem, 0, VK_WHOLE_SIZE, 0, &data);
if (result != VK_SUCCESS) {
LOGE("VulkanExample load2x2ShadingRate: Failed to map memory, result: %{public}d", result);
file.Close();
return;
}

// Read image data
char* imageData = (char*)data + subResourceLayout.offset;
if (file.Read(imageData, savedSize) != savedSize) {
LOGE("VulkanExample load2x2ShadingRate: Failed to read image data");
} else {
LOGI("VulkanExample load2x2ShadingRate: Successfully loaded %{public}llu bytes", savedSize);
}

file.Close();
vkUnmapMemory(device, frameBuffers.shadingRate.color.mem);

LOGI("VulkanExample load2x2ShadingRate: Successfully loaded 2x2 shading rate image");
}
5 changes: 5 additions & 0 deletions entry/src/main/cpp/render/model_3d_sponza.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,10 @@ class VulkanExample : public VulkanExampleBase {
// Methods for saving and loading shading rate image data
void saveShadingRateImage();
void loadShadingRateImage();

// Methods for 2x2 shading rate functionality
void generate2x2ShadingRate();
void save2x2ShadingRate();
void load2x2ShadingRate();
};
#endif // RENDER_MODEL_3D_SPONZA_H
86 changes: 85 additions & 1 deletion entry/src/main/cpp/render/plugin_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,88 @@ napi_value PluginRender::SetLoadShadingImage(napi_env env, napi_callback_info in
return nullptr;
}

napi_value PluginRender::Save2x2ShadingRate(napi_env env, napi_callback_info info)
{
LOGI("PluginRender::Save2x2ShadingRate called");

if ((nullptr == env) || (nullptr == info)) {
LOGE("PluginRender Save2x2ShadingRate : env or info is null");
return nullptr;
}

napi_value thisArg;
if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) {
LOGE("PluginRender Save2x2ShadingRate : napi_get_cb_info fail");
return nullptr;
}

napi_value exportInstance;
if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
LOGE("PluginRender Save2x2ShadingRate : napi_get_named_property fail");
return nullptr;
}

OH_NativeXComponent *nativeXComponent = nullptr;
if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
LOGE("PluginRender Save2x2ShadingRate : napi_unwrap fail");
return nullptr;
}

char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
LOGE("PluginRender Save2x2ShadingRate : Unable to get XComponent id");
return nullptr;
}
std::string id(idStr);
PluginRender *render = PluginRender::GetInstance(id);
if (render && render->m_vulkanexample) {
render->m_vulkanexample->save2x2ShadingRate();
}
return nullptr;
}

napi_value PluginRender::Load2x2ShadingRate(napi_env env, napi_callback_info info)
{
LOGI("PluginRender::Load2x2ShadingRate called");

if ((nullptr == env) || (nullptr == info)) {
LOGE("PluginRender Load2x2ShadingRate : env or info is null");
return nullptr;
}

napi_value thisArg;
if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) {
LOGE("PluginRender Load2x2ShadingRate : napi_get_cb_info fail");
return nullptr;
}

napi_value exportInstance;
if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
LOGE("PluginRender Load2x2ShadingRate : napi_get_named_property fail");
return nullptr;
}

OH_NativeXComponent *nativeXComponent = nullptr;
if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
LOGE("PluginRender Load2x2ShadingRate : napi_unwrap fail");
return nullptr;
}

char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
LOGE("PluginRender Load2x2ShadingRate : Unable to get XComponent id");
return nullptr;
}
std::string id(idStr);
PluginRender *render = PluginRender::GetInstance(id);
if (render && render->m_vulkanexample) {
render->m_vulkanexample->load2x2ShadingRate();
}
return nullptr;
}

PluginRender::PluginRender(std::string &id)
{
this->m_id = id;
Expand Down Expand Up @@ -320,7 +402,9 @@ void PluginRender::Export(napi_env env, napi_value exports)
{"setUpscaleMethod", nullptr, PluginRender::SetUpscaleMethod, nullptr, nullptr, nullptr, napi_default, nullptr},
{"setVRSUsed", nullptr, PluginRender::SetVRSUsed, nullptr, nullptr, nullptr, napi_default, nullptr},
{"saveShadingRateImage", nullptr, PluginRender::SaveShadingRateImage, nullptr, nullptr, nullptr, napi_default, nullptr},
{"setLoadShadingImage", nullptr, PluginRender::SetLoadShadingImage, nullptr, nullptr, nullptr, napi_default, nullptr}};
{"setLoadShadingImage", nullptr, PluginRender::SetLoadShadingImage, nullptr, nullptr, nullptr, napi_default, nullptr},
{"save2x2ShadingRate", nullptr, PluginRender::Save2x2ShadingRate, nullptr, nullptr, nullptr, napi_default, nullptr},
{"load2x2ShadingRate", nullptr, PluginRender::Load2x2ShadingRate, nullptr, nullptr, nullptr, napi_default, nullptr}};

if (napi_ok != napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)) {
LOGE("PluginRender Export: napi_define_properties failed");
Expand Down
2 changes: 2 additions & 0 deletions entry/src/main/cpp/render/plugin_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class PluginRender {
static napi_value SetVRSUsed(napi_env env, napi_callback_info info);
static napi_value SaveShadingRateImage(napi_env env, napi_callback_info info);
static napi_value SetLoadShadingImage(napi_env env, napi_callback_info info);
static napi_value Save2x2ShadingRate(napi_env env, napi_callback_info info);
static napi_value Load2x2ShadingRate(napi_env env, napi_callback_info info);
static std::unordered_map<std::string, PluginRender *> m_instance;
static OH_NativeXComponent_Callback m_callback;
static std::mutex m_mutex;
Expand Down
35 changes: 35 additions & 0 deletions entry/src/main/ets/pages/Index.ets
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,41 @@ struct Index {

}.height('10%').width('90%')

Row() {
Column() {
Button('Generate & Save 2x2')
.fontSize(12)
.fontWeight(500)
.fontColor('#FFFFFF')
.backgroundColor('#FF6347')
.height(30)
.borderRadius(5)
.onClick(() => {
if (this.xComponentContext) {
this.xComponentContext.save2x2ShadingRate();
console.info('Generate & Save 2x2 Shading Rate button clicked')
}
})
}.width('50%')

Column() {
Button('Load 2x2 Shading Rate')
.fontSize(12)
.fontWeight(500)
.fontColor('#FFFFFF')
.backgroundColor('#4682B4')
.height(30)
.borderRadius(5)
.onClick(() => {
if (this.xComponentContext) {
this.xComponentContext.load2x2ShadingRate();
console.info('Load 2x2 Shading Rate button clicked')
}
})
}.width('50%')

}.height('10%').width('90%')

}.width('100%').height('100%').align(Alignment.TopStart)
}
}